📄 cpi_playlistitem.c
字号:
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "globals.h"
#include "CPI_Playlist.h"
#include "CPI_PlaylistItem.h"
#include "CPI_PlaylistItem_Internal.h"
#include "CPI_ID3.h"
void CPLI_OGG_SkipOverTab(FILE* pFile);
void CPLI_SetPath(CPs_PlaylistItem* pItem, const char* pcNewPath);
void CPLI_ReadTag_ID3v1(CPs_PlaylistItem* pItem, HANDLE hFile);
void CPLI_ReadTag_ID3v2(CPs_PlaylistItem* pItem, HANDLE hFile);
//void CPLI_ReadTag_OGG(CPs_PlaylistItem* pItem);
void CPLI_WriteTag_ID3v1(CPs_PlaylistItem* pItem, HANDLE hFile);
void CPLI_WriteTag_ID3v2(CPs_PlaylistItem* pItem, HANDLE hFile);
//void CPLI_WriteTag_OGG(CPs_PlaylistItem* pItem, HANDLE hFile);
//void CPLI_CalculateLength_OGG(CPs_PlaylistItem* pItem);
void CPLI_CalculateLength_MP3(CPs_PlaylistItem* pItem);
void CPLI_ShrinkFile(HANDLE hFile, const DWORD dwStartOffset, const unsigned int iNumBytes);
BOOL CPLI_GrowFile(HANDLE hFile, const DWORD dwStartOffset, const unsigned int iNumBytes);
////////////////////////////////////////////////////////////////////////////////
//
//
//
CP_HPLAYLISTITEM CPLII_CreateItem(const char* pcPath)
{
CPs_PlaylistItem* pNewItem = (CPs_PlaylistItem*)malloc(sizeof(CPs_PlaylistItem));
pNewItem->m_pcPath = NULL;
CPLI_SetPath(pNewItem, pcPath);
pNewItem->m_cTrackStackPos_AsText[0] = '\0';
pNewItem->m_iTrackStackPos = CIC_TRACKSTACK_UNSTACKED;
pNewItem->m_enTagType = ttUnread;
pNewItem->m_bID3Tag_SaveRequired = FALSE;
pNewItem->m_bDestroyOnDeactivate = FALSE;
pNewItem->m_pcArtist = NULL;
pNewItem->m_pcAlbum = NULL;
pNewItem->m_pcTrackName = NULL;
pNewItem->m_pcComment = NULL;
pNewItem->m_pcYear = NULL;
pNewItem->m_cGenre = CIC_INVALIDGENRE;
pNewItem->m_cTrackNum = CIC_INVALIDTRACKNUM;
pNewItem->m_pcTrackNum_AsText = NULL;
pNewItem->m_iTrackLength = 0;
pNewItem->m_pcTrackLength_AsText = NULL;
pNewItem->m_iCookie = -1;
pNewItem->m_hNext = NULL;
pNewItem->m_hPrev = NULL;
return pNewItem;
}
//
//
//
void CPLII_RemoveTagInfo(CPs_PlaylistItem* pItem)
{
if(pItem->m_pcArtist)
{
free(pItem->m_pcArtist);
pItem->m_pcArtist = NULL;
}
if(pItem->m_pcAlbum)
{
free(pItem->m_pcAlbum);
pItem->m_pcAlbum = NULL;
}
if(pItem->m_pcTrackName)
{
free(pItem->m_pcTrackName);
pItem->m_pcTrackName = NULL;
}
if(pItem->m_pcComment)
{
free(pItem->m_pcComment);
pItem->m_pcComment = NULL;
}
if(pItem->m_pcYear)
{
free(pItem->m_pcYear);
pItem->m_pcYear = NULL;
}
if(pItem->m_pcTrackNum_AsText)
{
free(pItem->m_pcTrackNum_AsText);
pItem->m_pcTrackNum_AsText = NULL;
}
if(pItem->m_pcTrackLength_AsText)
{
free(pItem->m_pcTrackLength_AsText);
pItem->m_pcTrackLength_AsText = NULL;
}
pItem->m_cGenre = CIC_INVALIDGENRE;
pItem->m_iTrackLength = 0;
pItem->m_cTrackNum = CIC_INVALIDTRACKNUM;
pItem->m_enTagType = ttUnread;
pItem->m_bID3Tag_SaveRequired = FALSE;
}
//
//
//
void CPLII_DestroyItem(CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
CPLII_RemoveTagInfo(pItem);
free(pItem->m_pcPath);
free(pItem);
}
//
//
//
const char* CPLI_GetPath(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcPath;
}
//
//
//
const char* CPLI_GetFilename(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcFilename;
}
//
//
//
int CPLI_GetTrackStackPos(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_iTrackStackPos;
}
//
//
//
const char* CPLI_GetTrackStackPos_AsText(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_cTrackStackPos_AsText;
}
//
//
//
const char* CPLI_GetArtist(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcArtist;
}
//
//
//
const char* CPLI_GetAlbum(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcAlbum;
}
//
//
//
const char* CPLI_GetTrackName(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcTrackName;
}
//
//
//
const char* CPLI_GetComment(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcComment;
}
//
//
//
const char* CPLI_GetYear(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcYear;
}
//
//
//
const char* CPLI_GetGenre(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
if(pItem->m_cGenre == CIC_INVALIDGENRE)
return NULL;
return glb_pcGenres[pItem->m_cGenre];
}
//
//
//
const unsigned char CPLI_GetTrackNum(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_cTrackNum;
}
//
//
//
const char* CPLI_GetTrackNum_AsText(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcTrackNum_AsText;
}
//
//
//
const char* CPLI_GetTrackLength_AsText(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_pcTrackLength_AsText;
}
//
//
//
int CPLI_GetTrackLength(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_iTrackLength;
}
//
//
//
void CPLI_SetCookie(CP_HPLAYLISTITEM hItem, const int iCookie)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
pItem->m_iCookie = iCookie;
}
//
//
//
int CPLI_GetCookie(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_iCookie;
}
//
//
//
CP_HPLAYLISTITEM CPLI_Next(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_hNext;
}
//
//
//
CP_HPLAYLISTITEM CPLI_Prev(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_hPrev;
}
//
//
//
char* DecodeID3String(const char* pcSource, const int iLength)
{
char* cWorkString = (char*)_alloca(iLength+1);
char* pDestString;
char* pcLastWhiteSpace;
int iCharIDX;
cWorkString[iLength] = '\0';
memcpy(cWorkString, pcSource, iLength);
// Remove trailing whitespace
pcLastWhiteSpace = NULL;
for(iCharIDX = 0; cWorkString[iCharIDX]; iCharIDX++)
{
if(cWorkString[iCharIDX] == ' ')
{
if(!pcLastWhiteSpace)
pcLastWhiteSpace = cWorkString + iCharIDX;
}
else
pcLastWhiteSpace = NULL;
}
if(pcLastWhiteSpace)
*pcLastWhiteSpace = '\0';
// Copy string
STR_AllocSetString(&pDestString, cWorkString, FALSE);
return pDestString;
}
//
//
//
void CPLI_ReadTag(CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
HANDLE hFile;
CP_CHECKOBJECT(pItem);
if(pItem->m_enTagType != ttUnread)
return;
// - Try to open the file
hFile = CreateFile(pItem->m_pcPath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
// Cannot open - fail silently
if(hFile == INVALID_HANDLE_VALUE)
return;
// Try to read a V2 tag
if(options.support_id3v2)
CPLI_ReadTag_ID3v2(pItem, hFile);
// Failed? - try a V1 tag instead
if(pItem->m_enTagType == ttUnread)
CPLI_ReadTag_ID3v1(pItem, hFile);
CloseHandle(hFile);
// Update interface
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
char* CPLI_ID3v2_DecodeString(const BYTE* pSourceText, const int iTagDataSize)
{
int iStringLength;
char* pcDestString;
if(pSourceText[0] == '\0')
{
iStringLength = iTagDataSize-1;
pcDestString = malloc(iStringLength+1);
memcpy(pcDestString, pSourceText+1, iStringLength);
pcDestString[iStringLength] = 0;
}
else
{
CP_TRACE0("ID3v2 Unknown encoding");
pcDestString = NULL;
}
return pcDestString;
}
//
//
//
void CPLI_DecodeLength(CPs_PlaylistItem* pItem, unsigned int iNewLength)
{
int iHours, iMins, iSecs;
// Free existing buffer
if(pItem->m_pcTrackLength_AsText)
{
free(pItem->m_pcTrackLength_AsText);
pItem->m_pcTrackLength_AsText = NULL;
}
pItem->m_iTrackLength = iNewLength;
iHours = iNewLength/3600;
iMins = (iNewLength-(iHours*3600)) / 60;
iSecs = iNewLength - (iHours*3600) - (iMins*60);
// If length has hours then format as hh:mm:ss otherwise format as mm:ss
if(iHours > 0)
{
pItem->m_pcTrackLength_AsText = (char*)malloc(9);
sprintf(pItem->m_pcTrackLength_AsText, "%02d:%02d:%02d", iHours, iMins, iSecs);
}
else
{
pItem->m_pcTrackLength_AsText = (char*)malloc(6);
sprintf(pItem->m_pcTrackLength_AsText, "%02d:%02d", iMins, iSecs);
}
}
//
//
//
void CPLI_ReadTag_ID3v2(CPs_PlaylistItem* pItem, HANDLE hFile)
{
DWORD dwBytesRead;
int iTagDataToRead;
CIs_ID3v2Tag ID3v2;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, &ID3v2, sizeof(ID3v2), &dwBytesRead, NULL);
// Not enough file data returned - or the data returned does not look like an ID3
if(dwBytesRead != sizeof(ID3v2)
|| memcmp(ID3v2.m_cTAG, "ID3", 3) != 0
|| (ID3v2.m_cVersion[0] != 0x03 && ID3v2.m_cVersion[0] != 0x04)) // Major version wrong
{
return;
}
// Work out the amount of tag left to read
iTagDataToRead = (ID3v2.m_cSize_Encoded[0] << 21)
| (ID3v2.m_cSize_Encoded[1] << 14)
| (ID3v2.m_cSize_Encoded[2] << 7)
| ID3v2.m_cSize_Encoded[3];
// Check for a big enough file now (to save endless checking)
if(GetFileSize(hFile, NULL) < (sizeof(ID3v2) + iTagDataToRead))
return;
// Skip over extended header (if there is one)
if(ID3v2.m_cFlags & ID3v2_FLAG_EXTENDEDHEADER)
{
char cExtendedHeaderSize_Encoded[4];
int iExtendedHeaderSize;
ReadFile(hFile, cExtendedHeaderSize_Encoded, sizeof(cExtendedHeaderSize_Encoded), &dwBytesRead, NULL);
iExtendedHeaderSize = (cExtendedHeaderSize_Encoded[0] << 21)
| (cExtendedHeaderSize_Encoded[1] << 14)
| (cExtendedHeaderSize_Encoded[2] << 7)
| cExtendedHeaderSize_Encoded[3];
SetFilePointer(hFile, iExtendedHeaderSize - sizeof(cExtendedHeaderSize_Encoded), NULL, FILE_CURRENT);
iTagDataToRead -= iExtendedHeaderSize;
}
while(iTagDataToRead > sizeof(CIs_ID3v2Frame))
{
CIs_ID3v2Frame ID3v2Frame;
BYTE* pFrameData;
int iFrameSize;
ReadFile(hFile, &ID3v2Frame, sizeof(ID3v2Frame), &dwBytesRead, NULL);
// Have we encountered padding?
if(ID3v2Frame.m_cFrameID[0] == '\0')
break;
if(ID3v2.m_cVersion[0] == 0x03)
{
iFrameSize = (ID3v2Frame.m_cSize_Encoded[0] << 24)
| (ID3v2Frame.m_cSize_Encoded[1] << 16)
| (ID3v2Frame.m_cSize_Encoded[2] << 8)
| ID3v2Frame.m_cSize_Encoded[3];
}
else
{
iFrameSize = (ID3v2Frame.m_cSize_Encoded[0] << 21)
| (ID3v2Frame.m_cSize_Encoded[1] << 14)
| (ID3v2Frame.m_cSize_Encoded[2] << 7)
| ID3v2Frame.m_cSize_Encoded[3];
}
// Frame size invalid?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -