CPI_PlaylistItem.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:44k
- ////////////////////////////////////////////////////////////////////////////////
- #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] = ' ';
- 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] = ' ';
- 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 = ' ';
- // 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] == ' ')
- {
- 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] == ' ')
- 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?
- if(iFrameSize > iTagDataToRead)
- return;
- pFrameData = malloc(iFrameSize+1);
- if(!ReadFile(hFile, pFrameData, iFrameSize, &dwBytesRead, NULL)) return;
- pFrameData[iFrameSize] = ' ';
- // 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] == ' ' || 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] = ' ';
- 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] == ' ')
- 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;
- 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] = ' ';
- }
- else if(iNewPos == CIC_TRACKSTACK_UNSTACKED)
- {
- pItem->m_cTrackStackPos_AsText[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] = ' ';
- }
- 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;
- }
- //
- //
- //