📄 cpi_playlist.c
字号:
break;
}
hCursor_Scan = CPLI_Next(hCursor_Scan);
}
hCursor = CPLI_Next(hCursor);
}
}
//
//
//
void CPL_PlayActiveItem(CP_HPLAYLIST hPlaylist, const BOOL bStopFirst)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
// Stop
if(bStopFirst == TRUE)
CPI_Player__Stop(globals.m_hPlayer);
// Start playing
if(pPlaylist->m_hCurrent)
{
CPI_Player__OpenFile(globals.m_hPlayer, CPLI_GetPath(pPlaylist->m_hCurrent));
CPI_Player__Play(globals.m_hPlayer);
}
}
//
//
//
void CPL_RemoveItem(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
// Callback
CPL_cb_OnPlaylistItemDelete(hItem);
CPL_UnlinkItem(hPlaylist, hItem);
// Remove item from track stack
CPL_Stack_Remove(hPlaylist, hItem);
if(hItem == pPlaylist->m_hCurrent)
{
// This is the active item - clear it's next and prev entries and mark it
// so that it's destroyed when activation next changes
CPs_PlaylistItem* pActiveItem = CPLII_DECODEHANDLE(hItem);
pActiveItem->m_hNext = NULL;
pActiveItem->m_hPrev = NULL;
pActiveItem->m_bDestroyOnDeactivate = TRUE;
CPL_cb_OnPlaylistActivationChange(hItem, FALSE);
pActiveItem->m_iCookie = CPC_INVALIDITEM;
}
else
{
// Cleanup
CPLII_DestroyItem(hItem);
}
}
//
//
//
void CPL_SetActiveItem(CP_HPLAYLIST hPlaylist, CP_HPLAYLISTITEM hItem)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
if(pPlaylist->m_hCurrent == hItem)
return;
// Unset any previous activation state
if(pPlaylist->m_hCurrent)
{
if(CPLII_DECODEHANDLE(pPlaylist->m_hCurrent)->m_bDestroyOnDeactivate)
CPLII_DestroyItem(pPlaylist->m_hCurrent);
else
CPL_cb_OnPlaylistActivationChange(pPlaylist->m_hCurrent, FALSE);
}
pPlaylist->m_hCurrent = hItem;
// Set new activation state
if(pPlaylist->m_hCurrent)
{
CPL_cb_OnPlaylistActivationChange(pPlaylist->m_hCurrent, TRUE);
if(options.read_id3_tag_of_selected == TRUE)
CPLI_ReadTag(hItem);
}
else
CPL_cb_OnPlaylistActivationEmpty();
// Update track stack
CPL_Stack_SetCursor(hPlaylist, pPlaylist->m_hCurrent);
// Setup the initial file buffer (for remember last played)
if(pPlaylist->m_hCurrent)
strncpy(options.initial_file, CPLI_GetPath(hItem), sizeof(options.initial_file));
}
//
//
//
void CPL_PlayItem(CP_HPLAYLIST hPlaylist, const BOOL bStopFirst, const CPe_PlayMode enPlayMode)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_HPLAYLISTITEM hItemToPlay = NULL;
CP_CHECKOBJECT(pPlaylist);
// Decide on what to play
switch(enPlayMode)
{
case pmCurrentItem:
if(pPlaylist->m_hCurrent)
{
// If the current item is no longer in the list and we are stopping - play the first item
if(bStopFirst == TRUE || CPLII_DECODEHANDLE(pPlaylist->m_hCurrent)->m_bDestroyOnDeactivate)
{
if(pPlaylist->m_iTrackStackSize > 0)
{
if(pPlaylist->m_iTrackStackCursor < pPlaylist->m_iTrackStackSize)
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor];
else
hItemToPlay = pPlaylist->m_pTrackStack[0];
}
}
else
hItemToPlay = pPlaylist->m_hCurrent;
}
else
{
if(pPlaylist->m_iTrackStackCursor < pPlaylist->m_iTrackStackSize)
{
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor];
}
else
{
if(options.shuffle_play)
CPL_Stack_Shuffle(globals.m_hPlaylist, FALSE);
if(pPlaylist->m_iTrackStackSize > 0)
hItemToPlay = pPlaylist->m_pTrackStack[0];
}
}
break;
case pmNextItem:
// If the currently playing track is not the one at the head of the stack - play the head of the stack
if(pPlaylist->m_hCurrent
&& pPlaylist->m_iTrackStackCursor < pPlaylist->m_iTrackStackSize
&& pPlaylist->m_hCurrent != pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor])
{
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor];
}
// Play the next item from the track stack
if(hItemToPlay == NULL)
{
if(pPlaylist->m_iTrackStackCursor < pPlaylist->m_iTrackStackSize)
pPlaylist->m_iTrackStackCursor++;
if(pPlaylist->m_iTrackStackCursor < pPlaylist->m_iTrackStackSize)
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor];
}
if(hItemToPlay == NULL && options.repeat_playlist == TRUE)
{
if(options.shuffle_play)
CPL_Stack_Shuffle(globals.m_hPlaylist, FALSE);
if(pPlaylist->m_iTrackStackSize > 0)
hItemToPlay = pPlaylist->m_pTrackStack[0];
}
break;
case pmPrevItem:
// Play the prev item in the track stack
if(pPlaylist->m_iTrackStackCursor > 0)
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackCursor-1];
else
{
if(options.repeat_playlist == TRUE)
{
if(pPlaylist->m_iTrackStackSize > 0)
hItemToPlay = pPlaylist->m_pTrackStack[pPlaylist->m_iTrackStackSize-1];
}
else if(pPlaylist->m_iTrackStackSize > 0)
hItemToPlay = pPlaylist->m_pTrackStack[0];
}
break;
default:
CP_FAIL(UnknownPlayMode);
}
CPL_SetActiveItem(hPlaylist, hItemToPlay);
CPL_PlayActiveItem(hPlaylist, bStopFirst);
}
//
//
//
CP_HPLAYLISTITEM CPL_GetFirstItem(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
return pPlaylist->m_hFirst;
}
//
//
//
CP_HPLAYLISTITEM CPL_GetLastItem(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
return pPlaylist->m_hLast;
}
//
//
//
CP_HPLAYLISTITEM CPL_GetActiveItem(CP_HPLAYLIST hPlaylist)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_CHECKOBJECT(pPlaylist);
return pPlaylist->m_hCurrent;
}
//
//
//
CP_HPLAYLISTITEM CPL_FindPlaylistItem(CP_HPLAYLIST hPlaylist, const char* pcPath)
{
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
CP_HPLAYLISTITEM hCursor;
CP_CHECKOBJECT(pPlaylist);
for(hCursor = pPlaylist->m_hFirst; hCursor; hCursor = CPLI_Next(hCursor))
{
CP_TRACE1("Looked at \"%s\"", CPLII_DECODEHANDLE(hCursor)->m_pcPath);
if(stricmp(CPLII_DECODEHANDLE(hCursor)->m_pcPath, pcPath) == 0)
return hCursor;
}
return NULL;
}
//
//
//
void WriteFile_Text(HANDLE hFile, const char* pcLine, const BOOL bAppendCR)
{
DWORD dwBytesWritten;
int iLineLen = strlen(pcLine);
WriteFile(hFile, pcLine, iLineLen, &dwBytesWritten, NULL);
if(bAppendCR)
WriteFile(hFile, "\r\n", 2, &dwBytesWritten, NULL);
}
//
//
//
CPe_PlayListFileType CPL_GetFileType(const char* pcPath)
{
// Determine format from file extension
const char* pcExtension = NULL;
int iCharIDX;
// Find the extension (the chars after the last dot)
for(iCharIDX = 0; pcPath[iCharIDX]; iCharIDX++)
{
if(pcPath[iCharIDX] == '.')
pcExtension = pcPath + iCharIDX + 1;
else if(pcPath[iCharIDX] == '\\')
pcExtension = NULL;
}
// No extension - we don't know what format to use!
if(pcExtension == NULL)
return pftUnknown;
if(stricmp(pcExtension, "pls") == 0)
return pftPLS;
else if(stricmp(pcExtension, "m3u") == 0)
return pftM3U;
return pftUnknown;
}
//
//
//
unsigned int CPL_GetPathVolumeBytes(const char* pcPath)
{
// We understand volumes in the format of C:\ or \\SYSTEMNAME\SHAREPOINT\ so look for
// these
if(pcPath[1] == ':')
return 3;
else if(pcPath[0] == '\\' && pcPath[1] == '\\')
{
int iCharIDX;
int iNumSlashesFound;
// UNCs format is \\SERVER\SharePoint\path
// Find the second slash (skipping the double slash at the start)
iNumSlashesFound = 0;
for(iCharIDX = 2; pcPath[iCharIDX]; iCharIDX++)
{
if(pcPath[iCharIDX] == '\\')
iNumSlashesFound++;
// We've found the second slash - build the prefix
if(iNumSlashesFound == 2)
return iCharIDX+1;
}
}
else if(strnicmp(pcPath, CIC_HTTPHEADER, sizeof(CIC_HTTPHEADER)-1) == 0)
return sizeof(CIC_HTTPHEADER);
// There is no volume information
return 0;
}
//
//
//
unsigned int CPL_GetPathDirectoryBytes(const char* pcPath, const unsigned int iVolumeBytes)
{
unsigned int iCharIDX;
unsigned int iLastSlashIDX;
// Find the last slash and trim everything before it
// - if there is no directory stub then empty this string
iLastSlashIDX = 0;
for(iCharIDX = iVolumeBytes; pcPath[iCharIDX]; iCharIDX++)
{
if(pcPath[iCharIDX] == '\\')
iLastSlashIDX = iCharIDX + 1;
}
return iLastSlashIDX;
}
//
//
//
void CPL_ExportPlaylist(CP_HPLAYLIST hPlaylist, const char* pcOutputName)
{
HANDLE hOutputFile;
CPe_PlayListFileType enFileType;
CPs_Playlist* pPlaylist = (CPs_Playlist*)hPlaylist;
const unsigned int iPlaylist_VolumeBytes = CPL_GetPathVolumeBytes(pcOutputName);
const unsigned int iPlaylist_DirectoryBytes = CPL_GetPathDirectoryBytes(pcOutputName, iPlaylist_VolumeBytes);
CP_CHECKOBJECT(pPlaylist);
// Check for known file types
enFileType = CPL_GetFileType(pcOutputName);
if(enFileType == pftUnknown)
return;
// Open the file
hOutputFile = CreateFile(pcOutputName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hOutputFile == INVALID_HANDLE_VALUE)
{
MessageBox(windows.wnd_main, "Could not open file", "Error", MB_ICONERROR);
return;
}
// Go through all playlist items - outputting them to the file
{
CP_HPLAYLISTITEM hCursor;
int iFileNumber;
// If this is a PLS file then write some header info
if(enFileType == pftPLS)
{
int iNumberOfEntries =0;
char cNumEntriesLine[32];
WriteFile_Text(hOutputFile, "[PlayList]", TRUE);
// Count the number of playlist items
for(hCursor = pPlaylist->m_hFirst; hCursor; hCursor = CPLI_Next(hCursor))
iNumberOfEntries++;
sprintf(cNumEntriesLine, "NumberOfEntries=%d", iNumberOfEntries);
WriteFile_Text(hOutputFile, cNumEntriesLine, TRUE);
}
iFileNumber = 0;
for(hCursor = pPlaylist->m_hFirst; hCursor; hCursor = CPLI_Next(hCursor), iFileNumber++)
{
char cRelPath[MAX_PATH];
const char* _pcFilename = CPLI_GetPath(hCursor);
// We prefer relative paths in our playlist files - only works if playlist
// and target are on the same volume
if(strnicmp(_pcFilename, pcOutputName, iPlaylist_VolumeBytes) == 0)
{
// - so strip off the directory stubs that the file and playlist may have in common
const char* pcLastCommonSplitPoint = _pcFilename;
unsigned int iCharIDX;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -