📄 cpi_playlist.c
字号:
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
BOOL bFoundItem;
CP_CHECKOBJECT(pPlaylist);
CPLI_SetTrackStackPos(hItem, CIC_TRACKSTACK_UNSTACKED);
// Search stack for item - remove it if we find it and renumber all items from there onwards
bFoundItem = FALSE;
for(iStackIDX = 0; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
{
if(bFoundItem == FALSE && pPlaylist->m_pTrackStack[iStackIDX] == hItem)
{
pPlaylist->m_iTrackStackSize--;
if(iStackIDX < pPlaylist->m_iTrackStackCursor)
pPlaylist->m_iTrackStackCursor--;
bFoundItem = TRUE;
}
if(bFoundItem == TRUE && iStackIDX < pPlaylist->m_iTrackStackSize)
pPlaylist->m_pTrackStack[iStackIDX] = pPlaylist->m_pTrackStack[iStackIDX+1];
}
CPL_Stack_Renumber(hPlaylist);
if(bFoundItem == TRUE)
{
// If the trackstack is now empty - free the buffers
if(pPlaylist->m_iTrackStackSize == 0)
{
pPlaylist->m_iTrackStackBufferSize = 0;
free(pPlaylist->m_pTrackStack);
pPlaylist->m_pTrackStack = NULL;
}
CPL_cb_TrackStackChanged();
}
}
//
//
//
void CPL_Stack_SetCursor(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
// Search for the item and set the cursor to this item - if it isn't in the stack then
// add this item to the end (and move the cursor there)
for(iStackIDX = 0; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
{
if(pPlaylist->m_pTrackStack[iStackIDX] == hItem)
{
pPlaylist->m_iTrackStackCursor = iStackIDX;
break;
}
}
CPL_Stack_Renumber(hPlaylist);
}
//
//
//
void CPL_Stack_Clear(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
// Mark all items in stack as unstacked
for(iStackIDX = 0; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
CPLI_SetTrackStackPos(pPlaylist->m_pTrackStack[iStackIDX], CIC_TRACKSTACK_UNSTACKED);
// Clear the stack buffer
pPlaylist->m_iTrackStackSize = 0;
pPlaylist->m_iTrackStackBufferSize = 0;
pPlaylist->m_iTrackStackCursor = 0;
free(pPlaylist->m_pTrackStack);
pPlaylist->m_pTrackStack = NULL;
CPL_cb_TrackStackChanged();
}
//
//
//
void CPL_Stack_RestackAll(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_HPLAYLISTITEM hCursor;
CP_CHECKOBJECT(pPlaylist);
pPlaylist->m_iTrackStackSize = 0;
pPlaylist->m_iTrackStackCursor = 0;
for(hCursor = pPlaylist->m_hFirst; hCursor; hCursor = CPLI_Next(hCursor))
CPL_Stack_Append(hPlaylist, hCursor);
if(pPlaylist->m_hCurrent)
CPL_Stack_SetCursor(hPlaylist, pPlaylist->m_hCurrent);
}
//
//
//
CPe_ItemStackState CPL_Stack_GetItemState(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
// Mark all items in stack as unstacked
for(iStackIDX = 0; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
{
if(pPlaylist->m_pTrackStack[iStackIDX] == hItem)
{
if(iStackIDX < pPlaylist->m_iTrackStackCursor)
return issPlayed;
else if(iStackIDX == pPlaylist->m_iTrackStackCursor)
return issStacked_Top;
else
return issStacked;
}
}
return issUnstacked;
}
//
//
//
void CPL_Stack_Shuffle(CP_HPLAYLIST hPlaylist, const BOOL bForceCurrentToHead)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
if(pPlaylist->m_iTrackStackSize == 0)
return;
// Qsort stack
qsort(pPlaylist->m_pTrackStack, pPlaylist->m_iTrackStackSize, sizeof(CP_HPLAYLISTITEM*), cpl_sort_Random);
pPlaylist->m_iTrackStackCursor = 0;
if(pPlaylist->m_hCurrent)
{
// If there is a playing track - ensure that it is at position 0
if(bForceCurrentToHead == TRUE)
{
for(iStackIDX = 0; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
{
if(pPlaylist->m_pTrackStack[iStackIDX] == pPlaylist->m_hCurrent)
{
pPlaylist->m_pTrackStack[iStackIDX] = pPlaylist->m_pTrackStack[0];
pPlaylist->m_pTrackStack[0] = pPlaylist->m_hCurrent;
break;
}
}
}
else
{
// If the current song is still at the head - swap it with the last song (to prevent a double play)
if(pPlaylist->m_pTrackStack[0] == pPlaylist->m_hCurrent)
{
pPlaylist->m_pTrackStack[0] = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackSize-1];
pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackSize-1] = pPlaylist->m_hCurrent;
}
}
}
CPL_Stack_Renumber(hPlaylist);
}
//
//
//
void CPL_Stack_ClipFromCurrent(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
if(pPlaylist->m_iTrackStackSize == 0 || pPlaylist->m_iTrackStackCursor >= pPlaylist->m_iTrackStackSize)
return;
// Mark all items in stack as unstacked
for(iStackIDX = pPlaylist->m_iTrackStackCursor+1; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
CPLI_SetTrackStackPos(pPlaylist->m_pTrackStack[iStackIDX], CIC_TRACKSTACK_UNSTACKED);
pPlaylist->m_iTrackStackSize = pPlaylist->m_iTrackStackCursor+1;
CPL_cb_TrackStackChanged();
}
//
//
//
void CPL_Stack_ClipFromItem(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
BOOL bItemFound;
unsigned int iFoundItemIDX;
CP_CHECKOBJECT(pPlaylist);
if(pPlaylist->m_iTrackStackSize == 0)
return;
// Mark items in stack after item as unstacked
bItemFound = FALSE;
iFoundItemIDX = CPC_INVALIDITEM;
for(iStackIDX = pPlaylist->m_iTrackStackCursor; iStackIDX < pPlaylist->m_iTrackStackSize; iStackIDX++)
{
if(bItemFound == FALSE && pPlaylist->m_pTrackStack[iStackIDX] == hItem)
{
bItemFound = TRUE;
iFoundItemIDX = iStackIDX;
}
else if(bItemFound)
CPLI_SetTrackStackPos(pPlaylist->m_pTrackStack[iStackIDX], CIC_TRACKSTACK_UNSTACKED);
}
if(bItemFound)
{
pPlaylist->m_iTrackStackSize = iFoundItemIDX+1;
CPL_cb_TrackStackChanged();
}
}
//
//
//
void CPL_Stack_PlayNext(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
unsigned int iStackIDX;
CP_CHECKOBJECT(pPlaylist);
CPL_Stack_Remove(hPlaylist, hItem);
// Rationalise cursor
if(pPlaylist->m_iTrackStackCursor >= pPlaylist->m_iTrackStackSize)
{
CPL_Stack_Append(hPlaylist, hItem);
return;
}
// Simple case
if(pPlaylist->m_iTrackStackBufferSize == 0)
{
CPL_Stack_Append(hPlaylist, hItem);
return;
}
// Ensure buffer is big enough
if( (pPlaylist->m_iTrackStackSize+1) >= pPlaylist->m_iTrackStackBufferSize)
{
pPlaylist->m_iTrackStackBufferSize += CPC_TRACKSTACK_BUFFER_QUANTISATION;
pPlaylist->m_pTrackStack = realloc(pPlaylist->m_pTrackStack, pPlaylist->m_iTrackStackBufferSize * sizeof(CP_HPLAYLISTITEM));
}
// Shunt all items up one
for(iStackIDX = pPlaylist->m_iTrackStackSize; iStackIDX > (pPlaylist->m_iTrackStackCursor+1); iStackIDX--)
{
pPlaylist->m_pTrackStack[iStackIDX] = pPlaylist->m_pTrackStack[iStackIDX-1];
CPLI_SetTrackStackPos(pPlaylist->m_pTrackStack[iStackIDX], iStackIDX-pPlaylist->m_iTrackStackCursor);
}
// Add item
pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor+1] = hItem;
CPLI_SetTrackStackPos(pPlaylist->m_pTrackStack[iStackIDX], 1);
pPlaylist->m_iTrackStackSize++;
CPL_cb_TrackStackChanged();
}
//
//
//
DWORD WINAPI CPI_PlaylistWorkerThreadEP(void* pCookie)
{
CPs_PlaylistWorkerThreadInfo* pThreadInfo = (CPs_PlaylistWorkerThreadInfo*)pCookie;
MSG msg;
CPs_NotifyChunk* pPendingChunk;
BOOL bRet;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
pPendingChunk = NULL;
while((bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
return 0;
}
if(msg.message == CPPLWT_TERMINATE)
{
break;
}
else if(msg.message == CPPLWT_READTAG)
{
MSG msgPeek;
CP_HPLAYLISTITEM hNewFile = (CP_HPLAYLISTITEM)msg.lParam;
if(pThreadInfo->m_dwCurrentBatchID == (DWORD)msg.wParam)
{
CPLI_ReadTag(hNewFile);
// If we didn't get a track length from the tag - work it out
if(CPLI_GetTrackLength(hNewFile) == 0
&& options.work_out_track_lengths)
{
CPLI_CalculateLength(hNewFile);
}
// Allocate chunk
if(!pPendingChunk)
{
pPendingChunk = (CPs_NotifyChunk*)malloc(sizeof(CPs_NotifyChunk));
pPendingChunk->m_iNumberInChunk = 0;
}
// Add to current chunk
pPendingChunk->m_aryItems[pPendingChunk->m_iNumberInChunk] = hNewFile;
pPendingChunk->m_aryBatchIDs[pPendingChunk->m_iNumberInChunk] = (DWORD)msg.wParam;
pPendingChunk->m_iNumberInChunk++;
}
else
CPLII_DestroyItem(hNewFile);
// Send the current chunk if its full or there are no more pending readtag messages
if(pPendingChunk)
{
if(pPendingChunk->m_iNumberInChunk == CPC_PLAYLISTWORKER_NOTIFYCHUNKSIZE
|| PeekMessage(&msgPeek, NULL, CPPLWT_READTAG, CPPLWT_READTAG, PM_NOREMOVE) == FALSE)
{
PostThreadMessage(pThreadInfo->m_dwHostThreadID, CPPLNM_TAGREAD, (WPARAM)pPendingChunk, 0L);
pPendingChunk = NULL;
}
}
}
else if(msg.message == CPPLWT_SYNCSHUFFLE)
{
PostThreadMessage(pThreadInfo->m_dwHostThreadID, CPPLNM_SYNCSHUFFLE, 0L, 0L);
}
else if(msg.message == CPPLWT_SETACTIVE)
{
CP_HPLAYLISTITEM hFile = (CP_HPLAYLISTITEM)msg.lParam;
// Send the current chunk if there is one
if(pPendingChunk)
{
PostThreadMessage(pThreadInfo->m_dwHostThreadID, CPPLNM_TAGREAD, (WPARAM)pPendingChunk, 0L);
pPendingChunk = NULL;
}
// Send the setactivate
if(pThreadInfo->m_dwCurrentBatchID == (DWORD)msg.wParam)
PostThreadMessage(pThreadInfo->m_dwHostThreadID, CPPLNM_SYNCSETACTIVE, (WPARAM)hFile, 0L);
}
}
// Clean up any pending chunk
if(pPendingChunk)
{
int iChunkItemIDX;
for(iChunkItemIDX = 0; iChunkItemIDX < pPendingChunk->m_iNumberInChunk; iChunkItemIDX++)
CPLII_DestroyItem(pPendingChunk->m_aryItems[iChunkItemIDX]);
free(pPendingChunk);
}
CP_TRACE0("Playlist worker thread terminating");
return 0;
}
//
//
//
void CPL_SyncLoadNextFile(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
pPlaylist->m_bSyncLoadNextFile = TRUE;
}
//
//
//
void CPL_SetAutoActivateInitial(CP_HPLAYLIST hPlaylist, const BOOL bAutoActivateInitial)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
pPlaylist->m_bAutoActivateInitial = TRUE;
}
//
//
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -