?? cpi_playlistitem.c
字號:
if(iFrameSize > iTagDataToRead)
return;
pFrameData = malloc(iFrameSize+1);
if(!ReadFile(hFile, pFrameData, iFrameSize, &dwBytesRead, NULL)) return;
pFrameData[iFrameSize] = '\0';
// Decode frames
if(memcmp(ID3v2Frame.m_cFrameID, "TIT2", 4) == 0)
pItem->m_pcTrackName = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
else if(memcmp(ID3v2Frame.m_cFrameID, "TPE1", 4) == 0)
pItem->m_pcArtist = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
else if(memcmp(ID3v2Frame.m_cFrameID, "TALB", 4) == 0)
pItem->m_pcAlbum = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
else if(memcmp(ID3v2Frame.m_cFrameID, "TRCK", 4) == 0)
{
pItem->m_pcTrackNum_AsText = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
if(pItem->m_pcTrackNum_AsText)
pItem->m_cTrackNum = (unsigned char)atoi(pItem->m_pcTrackNum_AsText);
}
else if(memcmp(ID3v2Frame.m_cFrameID, "TYER", 4) == 0)
pItem->m_pcYear = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
else if(memcmp(ID3v2Frame.m_cFrameID, "TENC", 4) == 0)
pItem->m_pcComment = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
else if(memcmp(ID3v2Frame.m_cFrameID, "TCON", 4) == 0)
{
char* pcGenre = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
if(pcGenre)
{
// Search for this genre among the ID3v1 genres (don't read it if we cannot find it)
int iGenreIDX;
for(iGenreIDX = 0; iGenreIDX < CIC_NUMGENRES; iGenreIDX++)
{
if(stricmp(pcGenre, glb_pcGenres[iGenreIDX]) == 0)
{
pItem->m_cGenre = (unsigned char)iGenreIDX;
break;
}
}
free(pcGenre);
}
}
else if(memcmp(ID3v2Frame.m_cFrameID, "TLEN", 4) == 0)
{
char* pcLength = CPLI_ID3v2_DecodeString(pFrameData, iFrameSize);
if(pcLength)
{
CPLI_DecodeLength(pItem, atoi(pcLength)/1000);
free(pcLength);
}
}
#ifdef _DEBUG
/*
else if(ID3v2Frame.m_cFrameID[0] == 'T')
CP_TRACE2("Text frame %4s \"%s\"", ID3v2Frame.m_cFrameID, pFrameData+1);
else
CP_TRACE1("Any old frame %4s", ID3v2Frame.m_cFrameID);
*/
#endif
free(pFrameData);
iTagDataToRead -= iFrameSize + sizeof(ID3v2Frame);
}
pItem->m_enTagType = ttID3v2;
}
//
//
//
void CPLI_ReadTag_ID3v1(CPs_PlaylistItem* pItem, HANDLE hFile)
{
DWORD dwBytesRead;
CIs_ID3Tag ID3;
SetFilePointer(hFile, 0-sizeof(ID3), NULL, FILE_END);
ReadFile(hFile, &ID3, sizeof(ID3), &dwBytesRead, NULL);
// Not enough file data returned - or the data returned does not look like an ID3
if(dwBytesRead != sizeof(ID3) || memcmp(ID3.m_cTAG, "TAG", 3) != 0)
return;
// Decode the fixed strings into our dynamic strings
CPLII_RemoveTagInfo(pItem);
pItem->m_pcTrackName = DecodeID3String(ID3.m_cSong, 30);
pItem->m_pcArtist = DecodeID3String(ID3.m_cArtist, 30);
pItem->m_pcAlbum = DecodeID3String(ID3.m_cAlbum, 30);
pItem->m_pcYear = DecodeID3String(ID3.m_cYear, 4);
// ID3v1.1 - If the 29th byte of the comment is 0 then the 30th byte is the track num
// ** Some dodgy implementations of ID3v1.1 just slap a <32 char byte at position 30 and hope
// for the best - handle these too <hmph!>
if(ID3.m_cComment[28] == '\0' || ID3.m_cComment[29] < 32)
{
char cTempString[33];
pItem->m_pcComment = DecodeID3String(ID3.m_cComment, 28);
pItem->m_cTrackNum = ID3.m_cComment[29];
if(pItem->m_cTrackNum != CIC_INVALIDTRACKNUM)
{
itoa(pItem->m_cTrackNum, cTempString, 10);
pItem->m_pcTrackNum_AsText = (char*)malloc(CPC_TRACKNUMASTEXTBUFFERSIZE);
strncpy(pItem->m_pcTrackNum_AsText, cTempString, CPC_TRACKNUMASTEXTBUFFERSIZE);
}
}
else
{
pItem->m_pcComment = DecodeID3String(ID3.m_cComment, 30);
pItem->m_cTrackNum = CIC_INVALIDTRACKNUM;
}
if(ID3.m_cGenre < CIC_NUMGENRES)
pItem->m_cGenre = ID3.m_cGenre;
pItem->m_enTagType = ttID3v1;
}
//
//
//
BOOL CPLI_IsTagDirty(CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
return pItem->m_bID3Tag_SaveRequired;
}
//
//
//
void CPLI_WriteTag(CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
HANDLE hFile;
CP_CHECKOBJECT(pItem);
if(pItem->m_bID3Tag_SaveRequired == FALSE)
return;
if(stricmp(".ogg", CPLI_GetExtension(hItem)) != 0 &&
stricmp(".mp3", CPLI_GetExtension(hItem)) !=0)
return;
// Try to open the file
hFile = CreateFile(pItem->m_pcPath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
// Cannot open - fail silently
if(hFile == INVALID_HANDLE_VALUE)
return;
pItem->m_bID3Tag_SaveRequired = FALSE;
if (stricmp(".mp3", CPLI_GetExtension(hItem)) ==0)
{
CPLI_WriteTag_ID3v1(pItem, hFile);
if(options.support_id3v2)
CPLI_WriteTag_ID3v2(pItem, hFile);
}
CloseHandle(hFile);
}
//
//
//
void CPLI_WriteTag_ID3v1(CPs_PlaylistItem* pItem, HANDLE hFile)
{
DWORD dwBytesTransferred;
CIs_ID3Tag ID3;
char cTagMagic[3];
// Build the tag (of ID3v1.1 format)
memset(&ID3, 32, sizeof(ID3));
memcpy(ID3.m_cTAG, "TAG", 3);
if(pItem->m_pcTrackName)
strncpy(ID3.m_cSong, pItem->m_pcTrackName, 30);
if(pItem->m_pcArtist)
strncpy(ID3.m_cArtist, pItem->m_pcArtist, 30);
if(pItem->m_pcAlbum)
strncpy(ID3.m_cAlbum, pItem->m_pcAlbum, 30);
if(pItem->m_pcYear)
strncpy(ID3.m_cYear, pItem->m_pcYear, 4);
if(pItem->m_pcComment)
if(strlen(pItem->m_pcComment)>28)
{
strncpy(ID3.m_cComment, pItem->m_pcComment, 30);
}else
{
strncpy(ID3.m_cComment, pItem->m_pcComment, 28);
ID3.m_cComment[28] = '\0';
ID3.m_cComment[29] = pItem->m_cTrackNum;
}
ID3.m_cGenre = pItem->m_cGenre;
// Set the file pointer to the end of the file (or the start of the tag if there is one already)
SetFilePointer(hFile, 0-sizeof(ID3), NULL, FILE_END);
ReadFile(hFile, cTagMagic, sizeof(cTagMagic), &dwBytesTransferred, NULL);
if(memcmp(cTagMagic, "TAG", 3) == 0)
SetFilePointer(hFile, 0-sizeof(ID3), NULL, FILE_END);
else
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, &ID3, sizeof(ID3), &dwBytesTransferred, NULL);
}
//
//
//
void CPLI_ID3v2_WriteSyncSafeInt(char cDest[4], const int iSource)
{
cDest[0] = (iSource>>21) & 0x7F;
cDest[1] = (iSource>>14) & 0x7F;
cDest[2] = (iSource>>7) & 0x7F;
cDest[3] = iSource & 0x7F;
}
//
//
//
void CPLI_ID3v2_WriteTextFrame(BYTE** ppDest, const char pcTag[4], const char* pcString)
{
CIs_ID3v2Frame* pFrame = (CIs_ID3v2Frame*)*ppDest;
BYTE* pFrameData;
int iFrameDataLength;
iFrameDataLength = strlen(pcString) + 1; // 1-byte for encoding
memcpy(pFrame->m_cFrameID, pcTag, sizeof(pcTag));
CPLI_ID3v2_WriteSyncSafeInt(pFrame->m_cSize_Encoded, iFrameDataLength);
pFrame->m_cFlags = 0x0;
// Write frame data
pFrameData = ((*ppDest) + sizeof(CIs_ID3v2Frame));
pFrameData[0] = 0x0;
memcpy(pFrameData + 1, pcString, iFrameDataLength-1);
*ppDest += iFrameDataLength + sizeof(CIs_ID3v2Frame);
}
//
//
//
void CPLI_WriteTag_ID3v2(CPs_PlaylistItem* pItem, HANDLE hFile)
{
unsigned int iTagDataLength;
unsigned int iExistingTagLength;
DWORD dwBytesTransferred;
char atiobuffer[33];
BYTE* pTag;
BYTE* pTag_Cursor;
// Work out the size of the data in the tag frames
iTagDataLength = 0;
if(pItem->m_pcTrackName)
iTagDataLength += strlen(pItem->m_pcTrackName) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_pcArtist)
iTagDataLength += strlen(pItem->m_pcArtist) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_pcAlbum)
iTagDataLength += strlen(pItem->m_pcAlbum) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_pcYear)
iTagDataLength += strlen(pItem->m_pcYear) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_pcComment)
iTagDataLength += strlen(pItem->m_pcComment) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_cGenre != CIC_INVALIDGENRE)
iTagDataLength += strlen(glb_pcGenres[pItem->m_cGenre]) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_cTrackNum != CIC_INVALIDTRACKNUM)
iTagDataLength += strlen(itoa(pItem->m_cTrackNum, atiobuffer, 10)) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
if(pItem->m_iTrackLength != 0)
iTagDataLength += strlen(itoa(pItem->m_iTrackLength*1000, atiobuffer, 10)) + 1 + sizeof(CIs_ID3v2Frame); // 1-byte for encoding and a frame header
// Add ID3v2 overhead
iTagDataLength += sizeof(CIs_ID3v2Tag);
// Quantise tag to the nearest 1K
iTagDataLength = ((iTagDataLength>>10) + 1) << 10;
// Is there a tag big enough in the file
{
CIs_ID3v2Tag existingtagheader;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, &existingtagheader, sizeof(existingtagheader), &dwBytesTransferred, NULL);
if(memcmp(existingtagheader.m_cTAG, "ID3", 3) == 0)
{
iExistingTagLength = (existingtagheader.m_cSize_Encoded[0] << 21)
| (existingtagheader.m_cSize_Encoded[1] << 14)
| (existingtagheader.m_cSize_Encoded[2] << 7)
| existingtagheader.m_cSize_Encoded[3];
iExistingTagLength += sizeof(CIs_ID3v2Tag); // count the header
if(iExistingTagLength > iTagDataLength)
iTagDataLength = iExistingTagLength;
}
else
iExistingTagLength = 0;
}
// Do we need to enlarge the file?
if(iExistingTagLength < iTagDataLength)
{
if(CPLI_GrowFile(hFile, 0, iTagDataLength-iExistingTagLength) == FALSE)
return;
}
// Build tag
pTag = malloc(iTagDataLength);
memset(pTag, 0, iTagDataLength); // ** must do this as all padding should be 0x00
pTag_Cursor = pTag;
// Header
{
CIs_ID3v2Tag* pHeader = (CIs_ID3v2Tag*)pTag_Cursor;
int iSizeLessHeader = iTagDataLength - sizeof(CIs_ID3v2Tag);
pHeader->m_cTAG[0] = 'I';
pHeader->m_cTAG[1] = 'D';
pHeader->m_cTAG[2] = '3';
pHeader->m_cVersion[0] = 0x4;
pHeader->m_cVersion[1] = 0x0;
pHeader->m_cFlags = 0x0;
CPLI_ID3v2_WriteSyncSafeInt(pHeader->m_cSize_Encoded, iSizeLessHeader);
pTag_Cursor += sizeof(CIs_ID3v2Tag);
}
// Frames
if(pItem->m_pcTrackName)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TIT2", pItem->m_pcTrackName);
if(pItem->m_pcArtist)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TPE1", pItem->m_pcArtist);
if(pItem->m_pcAlbum)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TALB", pItem->m_pcAlbum);
if(pItem->m_pcYear)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TYER", pItem->m_pcYear);
if(pItem->m_pcComment)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TENC", pItem->m_pcComment);
if(pItem->m_cGenre != CIC_INVALIDGENRE)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TCON", glb_pcGenres[pItem->m_cGenre]);
if(pItem->m_cTrackNum != CIC_INVALIDTRACKNUM)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TRCK", itoa(pItem->m_cTrackNum, atiobuffer, 10));
if(pItem->m_iTrackLength != 0)
CPLI_ID3v2_WriteTextFrame(&pTag_Cursor, "TLEN", itoa(pItem->m_iTrackLength * 1000, atiobuffer, 10));
// Output tag
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
WriteFile(hFile, pTag, iTagDataLength, &dwBytesTransferred, NULL);
CP_ASSERT(dwBytesTransferred == iTagDataLength);
}
//
//
//
CPe_ReadWriteState CPLI_GetReadWriteState(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
HANDLE hFile;
CP_CHECKOBJECT(pItem);
// We will check this every time (and not cache the result) because the
// file could have been played with outside of CoolPlayer
// Try to open the file in RW mode
hFile = CreateFile(pItem->m_pcPath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
// Only cache
CloseHandle(hFile);
return rwsReadWrite;
}
// That didn't work - try a RO open
hFile = CreateFile(pItem->m_pcPath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
return rwsReadOnly;
}
return rwsBadFile;
}
//
//
//
void CPLI_SetArtist(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
STR_AllocSetString(&pItem->m_pcArtist, pcNewValue, TRUE);
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetAlbum(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
STR_AllocSetString(&pItem->m_pcAlbum, pcNewValue, TRUE);
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetTrackName(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
STR_AllocSetString(&pItem->m_pcTrackName, pcNewValue, TRUE);
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetYear(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
STR_AllocSetString(&pItem->m_pcYear, pcNewValue, TRUE);
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetGenreIDX(CP_HPLAYLISTITEM hItem, const unsigned char iNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
pItem->m_cGenre = iNewValue;
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetTrackNum(CP_HPLAYLISTITEM hItem, const unsigned char iNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
char cTempString[33];
CP_CHECKOBJECT(pItem);
pItem->m_cTrackNum = iNewValue;
if(pItem->m_cTrackNum != CIC_INVALIDTRACKNUM)
{
if(pItem->m_pcTrackNum_AsText)
free(pItem->m_pcTrackNum_AsText);
pItem->m_pcTrackNum_AsText = (char*)malloc(CPC_TRACKNUMASTEXTBUFFERSIZE);
itoa(pItem->m_cTrackNum, cTempString, 10);
strncpy(pItem->m_pcTrackNum_AsText, cTempString, CPC_TRACKNUMASTEXTBUFFERSIZE);
}
else
{
if(pItem->m_pcTrackNum_AsText)
{
free(pItem->m_pcTrackNum_AsText);
pItem->m_pcTrackNum_AsText = NULL;
}
}
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetTrackNum_AsText(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
if(pcNewValue[0] == '\0')
pItem->m_cTrackNum = CIC_INVALIDTRACKNUM;
else
pItem->m_cTrackNum = (unsigned char)atoi(pcNewValue);
if(pItem->m_pcTrackNum_AsText)
free(pItem->m_pcTrackNum_AsText);
pItem->m_pcTrackNum_AsText = (char*)malloc(CPC_TRACKNUMASTEXTBUFFERSIZE);
strncpy(pItem->m_pcTrackNum_AsText, pcNewValue, CPC_TRACKNUMASTEXTBUFFERSIZE);
pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetComment(CP_HPLAYLISTITEM hItem, const char* pcNewValue)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
STR_AllocSetString(&pItem->m_pcComment, pcNewValue, TRUE);
pItem->m_bID3Tag_SaveRequired = TRUE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -