?? cpi_playlistitem.c
字號:
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
void CPLI_SetTrackStackPos(CP_HPLAYLISTITEM hItem, const int iNewPos)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
CP_CHECKOBJECT(pItem);
pItem->m_iTrackStackPos = iNewPos;
if(iNewPos == 0)
{
pItem->m_cTrackStackPos_AsText[0] = '>';
pItem->m_cTrackStackPos_AsText[1] = '>';
pItem->m_cTrackStackPos_AsText[2] = '>';
pItem->m_cTrackStackPos_AsText[3] = '\0';
}
else if(iNewPos == CIC_TRACKSTACK_UNSTACKED)
{
pItem->m_cTrackStackPos_AsText[0] = '\0';
}
else
{
_snprintf(pItem->m_cTrackStackPos_AsText, sizeof(pItem->m_cTrackStackPos_AsText), "%d", iNewPos);
}
}
//
//
//
void CPLI_CalculateLength(CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
const char* pcExtension;
CP_CHECKOBJECT(pItem);
pcExtension = CPLI_GetExtension(hItem);
if(stricmp(pcExtension, ".mp3") == 0
|| stricmp(pcExtension, ".mp2") == 0)
{
CPLI_CalculateLength_MP3(pItem);
}
// pItem->m_bID3Tag_SaveRequired = TRUE;
CPL_cb_OnItemUpdated(hItem);
}
//
//
//
//
//
//
//
//
//
void CPLI_CalculateLength_MP3(CPs_PlaylistItem* pItem)
{
BYTE pbBuffer[0x8000];
unsigned int iBufferCursor;
DWORD dwBufferSize;
HANDLE hFile;
BOOL bFoundFrameHeader;
int iBitRate;
DWORD dwFileSize;
int iMPEG_version;
int iLayer;
BOOL bMono;
unsigned int iVBRHeader;
// - Try to open the file
hFile = CreateFile(pItem->m_pcPath, GENERIC_READ,
FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
dwFileSize = GetFileSize(hFile, NULL);
// Cannot open - fail silently
if(hFile == INVALID_HANDLE_VALUE)
return;
// Read the first 64K of the file (that should contain the first frame header!)
ReadFile(hFile, pbBuffer, sizeof(pbBuffer), &dwBufferSize, NULL);
CloseHandle(hFile);
iBufferCursor = 0;
// Skip over a any ID3v2 tag
{
CIs_ID3v2Tag* pHeader = (CIs_ID3v2Tag*)(pbBuffer + iBufferCursor);
if(memcmp(pHeader->m_cTAG, "ID3", 3) == 0)
{
iBufferCursor += (pHeader->m_cSize_Encoded[0] << 21)
| (pHeader->m_cSize_Encoded[1] << 14)
| (pHeader->m_cSize_Encoded[2] << 7)
| pHeader->m_cSize_Encoded[3];
iBufferCursor += sizeof(CIs_ID3v2Tag); // count the header
}
}
// Seek to the start of the first frame
bFoundFrameHeader = FALSE;
while(iBufferCursor < (dwBufferSize-4))
{
if(pbBuffer[iBufferCursor] == 0xFF
&& (pbBuffer[iBufferCursor+1] & 0xE0) == 0xE0)
{
bFoundFrameHeader = TRUE;
break;
}
iBufferCursor++;
}
if(bFoundFrameHeader == FALSE)
return;
// Work out MPEG version
if( ((pbBuffer[iBufferCursor+1] >> 3) & 0x3) == 0x3)
iMPEG_version = 1;
else
iMPEG_version = 2;
// Work out layer
iLayer = 0x4 - ( (pbBuffer[iBufferCursor+1] >> 1) & 0x3);
if(iLayer == 0)
return;
// Work out stereo
if( (pbBuffer[iBufferCursor+3]>>6) == 0x3)
bMono = TRUE;
else
bMono = FALSE;
// Work out the VBR header should be
if(iMPEG_version == 1)
iVBRHeader = (iBufferCursor+4) + (bMono ? 17 : 32);
else
iVBRHeader = (iBufferCursor+4) + (bMono ? 9 : 17);
// Is this a VBR file
if( (iBufferCursor+iVBRHeader+12) < dwBufferSize
&& pbBuffer[iVBRHeader]=='X'
&& pbBuffer[iVBRHeader+1]=='i'
&& pbBuffer[iVBRHeader+2]=='n'
&& pbBuffer[iVBRHeader+3]=='g')
{
int iNumberOfFrames;
int iFreq;
int iDetailedVersion;
const int aryFrequencies[3][3] = {
{44100, 48000, 32000}, //MPEG 1
{22050, 24000, 16000}, //MPEG 2
{32000, 16000, 8000} //MPEG 2.5
};
if( ((pbBuffer[iBufferCursor+1] >> 3) & 0x3) == 0x3)
iDetailedVersion = 1;
else if( ((pbBuffer[iBufferCursor+1] >> 3) & 0x3) == 0x2)
iDetailedVersion = 2;
else
iDetailedVersion = 3;
// Get the number of frames from the Xing header
iNumberOfFrames = (pbBuffer[iVBRHeader+8] << 24)
| (pbBuffer[iVBRHeader+9] << 16)
| (pbBuffer[iVBRHeader+10] << 8)
| pbBuffer[iVBRHeader+11];
if( ((pbBuffer[iBufferCursor+2]>>2) & 0x3) == 0x3)
return;
iFreq = aryFrequencies[iDetailedVersion-1][(pbBuffer[iBufferCursor+2]>>2) & 0x3];
CPLI_DecodeLength(pItem, (8 * iNumberOfFrames * 144)/iFreq);
}
// Work out the bit rate for a CBR file
else
{
const int aryBitRates[2][3][16] = {
{ //MPEG 2 & 2.5
{0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0}, //Layer I
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, //Layer II
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0} //Layer III
},{ //MPEG 1
{0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,0}, //Layer I
{0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, //Layer II
{0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,0} //Layer III
}
};
iBitRate = aryBitRates[2-iMPEG_version][iLayer-1][pbBuffer[iBufferCursor+2]>>4];
if(iBitRate)
CPLI_DecodeLength(pItem, (dwFileSize*8)/(iBitRate*1000) );
}
}
//
//
//
BOOL CPLI_RenameTrack(CP_HPLAYLISTITEM hItem, const CPe_FilenameFormat enFormat)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
char cPath[MAX_PATH];
char cNewPath[MAX_PATH];
BOOL bMoved;
const char* pcExtension;
CP_CHECKOBJECT(pItem);
strncpy(cPath, pItem->m_pcPath, MAX_PATH);
// Remove the filename from the path
{
int iLastSlashIDX, iCharIDX;
iLastSlashIDX = CPC_INVALIDCHAR;
for(iCharIDX = 0; cPath[iCharIDX]; iCharIDX++)
{
if(cPath[iCharIDX] == '\\')
iLastSlashIDX = iCharIDX;
}
if(iLastSlashIDX != CPC_INVALIDCHAR)
cPath[iLastSlashIDX] = '\0';
}
pcExtension = CPLI_GetExtension(hItem);
// Apply the name format
{
char cNewFilename[MAX_PATH];
const char* pcTitle;
const char* pcArtist;
const char* pcAlbum;
if(pItem->m_pcTrackName)
pcTitle = pItem->m_pcTrackName;
else
pcTitle = "<title>";
if(pItem->m_pcArtist)
pcArtist = pItem->m_pcArtist;
else
pcArtist = "<title>";
if(pItem->m_pcAlbum)
pcAlbum = pItem->m_pcAlbum;
else
pcAlbum = "<album>";
switch(enFormat)
{
case rwsArtistAlbumNumberTitle:
sprintf(cNewFilename, "%s - %s - %02d - %s%s", pcArtist, pcAlbum, (int)pItem->m_cTrackNum, pcTitle, pcExtension);
break;
case rwsArtistNumberTitle:
sprintf(cNewFilename, "%s - %02d - %s%s", pcArtist, (int)pItem->m_cTrackNum, pcTitle, pcExtension);
break;
case rwsAlbumNumberTitle:
sprintf(cNewFilename, "%s - %02d - %s%s", pcAlbum, (int)pItem->m_cTrackNum, pcTitle, pcExtension);
break;
case rwsAlbumNumber:
sprintf(cNewFilename, "%s - %02d%s", pcAlbum, (int)pItem->m_cTrackNum, pcExtension);
break;
case rwsNumberTitle:
sprintf(cNewFilename, "%02d - %s%s", (int)pItem->m_cTrackNum, pcTitle, pcExtension);
break;
case rwsTitle:
sprintf(cNewFilename, "%s%s", pcTitle, pcExtension);
break;
default:
CP_FAIL("Unknown rename format");
}
// Replace illegal chars with _
{
int iCharIDX;
for(iCharIDX = 0; cNewFilename[iCharIDX]; iCharIDX++)
{
if(cNewFilename[iCharIDX] == '\\'
|| cNewFilename[iCharIDX] == '/'
|| cNewFilename[iCharIDX] == ':'
|| cNewFilename[iCharIDX] == '"')
{
cNewFilename[iCharIDX] = '_';
}
}
}
sprintf(cNewPath, "%s\\%s", cPath, cNewFilename);
}
CP_TRACE2("Rename \"%s\" to \"%s\"", pItem->m_pcPath, cNewPath);
bMoved = MoveFile(pItem->m_pcPath, cNewPath);
if(bMoved)
{
CPLI_SetPath(pItem, cNewPath);
// Update interface
CPL_cb_OnItemUpdated(hItem);
}
return bMoved;
}
//
//
//
void CPLI_SetPath(CPs_PlaylistItem* pItem, const char* pcPath)
{
int iCharIDX, iLastSlashIDX;
char cFullPath[MAX_PATH];
if(pItem->m_pcPath)
free(pItem->m_pcPath);
// Store the full path to the file if this isn't a stream
if(strnicmp(CIC_HTTPHEADER, pcPath, 5) != 0
&& strnicmp("https:", pcPath, 6) != 0
&& strnicmp("ftp:", pcPath, 4) != 0)
{
_fullpath(cFullPath, pcPath, MAX_PATH);
STR_AllocSetString(&pItem->m_pcPath, cFullPath, FALSE);
}
else
STR_AllocSetString(&pItem->m_pcPath, pcPath, FALSE);
// Get the filename (the string following the last slash)
iLastSlashIDX = 0;
for(iCharIDX = 0; pItem->m_pcPath[iCharIDX]; iCharIDX++)
{
if(pItem->m_pcPath[iCharIDX] == '\\')
iLastSlashIDX = iCharIDX;
}
pItem->m_pcFilename = pItem->m_pcPath + iLastSlashIDX + 1;
}
//
//
//
const char* CPLI_GetExtension(const CP_HPLAYLISTITEM hItem)
{
CPs_PlaylistItem* pItem = (CPs_PlaylistItem*)hItem;
int iCharIDX;
const char* pcLastDot;
CP_CHECKOBJECT(pItem);
pcLastDot = NULL;
for(iCharIDX = 0; pItem->m_pcPath[iCharIDX]; iCharIDX++)
{
if(pItem->m_pcPath[iCharIDX] == '.')
pcLastDot = pItem->m_pcPath + iCharIDX;
// If there is a directory name with a dot in it we don't want that!
else if(pItem->m_pcPath[iCharIDX] == '\\')
pcLastDot = NULL;
}
// Ensure the string is valid
if(!pcLastDot)
pcLastDot = "";
return pcLastDot;
}
//
//
//
/*
void CPLI_OGG_SkipOverTab(FILE* pFile)
{
CIs_ID3v2Tag tag;
int iStreamStart = 0;
memset(&tag, 0, sizeof(tag));
fread(&tag, sizeof(tag), 1, pFile);
if(memcmp(tag.m_cTAG, "ID3", 3) == 0)
{
iStreamStart = sizeof(CIs_ID3v2Tag);
iStreamStart += (tag.m_cSize_Encoded[0] << 21)
| (tag.m_cSize_Encoded[1] << 14)
| (tag.m_cSize_Encoded[2] << 7)
| tag.m_cSize_Encoded[3];
}
fseek(pFile, iStreamStart, SEEK_SET);
}*/
//
//
//
/*void CPLI_OGG_DecodeString(char** ppcString, const char* pcNewValue)
{
int iStringLength;
if(*ppcString)
free(*ppcString);
iStringLength = strlen(pcNewValue);
*ppcString = malloc(iStringLength + 1);
memcpy(*ppcString, pcNewValue, iStringLength+1);
}*/
//
//
//
void CPLI_ShrinkFile(HANDLE hFile, const DWORD dwStartOffset, const unsigned int iNumBytes)
{
BYTE pBuffer[0x10000];
DWORD dwLength;
DWORD dwBytesTransferred;
DWORD dwCursor;
CP_TRACE1("Shrunking file by %d bytes", iNumBytes);
dwLength = GetFileSize(hFile, NULL);
CP_ASSERT( (dwStartOffset+iNumBytes) < dwLength);
dwCursor = dwStartOffset;
while((dwCursor+iNumBytes) < dwLength)
{
unsigned int iChunkSize;
iChunkSize = 0x10000;
if(iChunkSize > dwLength-(dwCursor+iNumBytes) )
iChunkSize = dwLength-(dwCursor+iNumBytes);
SetFilePointer(hFile, dwCursor + iNumBytes, NULL, FILE_BEGIN);
ReadFile(hFile, pBuffer, iChunkSize, &dwBytesTransferred, NULL);
CP_ASSERT(dwBytesTransferred == iChunkSize);
SetFilePointer(hFile, dwCursor, NULL, FILE_BEGIN);
WriteFile(hFile, pBuffer, iChunkSize, &dwBytesTransferred, NULL);
dwCursor += iChunkSize;
}
SetFilePointer(hFile, dwLength - iNumBytes, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
}
//
//
//
BOOL CPLI_GrowFile(HANDLE hFile, const DWORD dwStartOffset, const unsigned int iNumBytes)
{
DWORD dwFileSize;
unsigned int iFileCursor;
DWORD dwBytesTransferred;
BYTE* pbReadBlock[0x10000];
dwFileSize = GetFileSize(hFile, NULL);
CP_TRACE1("Enlarging file by %d bytes", iNumBytes);
// Try to write extra data to end of file - if we fail then clip the file and return
// (so that we don't corrupt the file in short of space situations)
{
BYTE* pbExtra;
pbExtra = (BYTE*)malloc(iNumBytes);
memset(pbExtra, 0, iNumBytes);
SetFilePointer(hFile, dwFileSize + iNumBytes, NULL, FILE_BEGIN);
WriteFile(hFile, pbExtra, iNumBytes, &dwBytesTransferred, NULL);
if(dwBytesTransferred != iNumBytes)
{
// Failed - clip file again and abort tag write
SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
return FALSE;
}
}
// Enlarge tag
iFileCursor = dwFileSize;
while(iFileCursor > dwStartOffset)
{
unsigned int iBlockSize;
iBlockSize = 0x10000;
if( (iFileCursor - dwStartOffset) < iBlockSize)
iBlockSize = iFileCursor - dwStartOffset;
// Read a chunk
SetFilePointer(hFile, iFileCursor - iBlockSize, NULL, FILE_BEGIN);
ReadFile(hFile, pbReadBlock, iBlockSize, &dwBytesTransferred, NULL);
CP_ASSERT(dwBytesTransferred == iBlockSize);
// Write chunk at offsetted position
SetFilePointer(hFile, iFileCursor - iBlockSize + iNumBytes, NULL, FILE_BEGIN);
WriteFile(hFile, pbReadBlock, iBlockSize, &dwBytesTransferred, NULL);
CP_ASSERT(dwBytesTransferred == iBlockSize);
iFileCursor -= iBlockSize;
}
return TRUE;
}
//
//
//
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -