mp3misc.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:14k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hlxclib/string.h"
  36. #include "hlxclib/stdlib.h"
  37. #include "hxtypes.h"
  38. #include "audinfo.h"
  39. #include "mp3misc.h"
  40. #include "dbcsutil.h"
  41. #include "hxassert.h"
  42. static char* StrNStr(const char* str1,
  43.                      const char* str2,
  44.                      size_t depth1,
  45.                      size_t depth2);
  46. eHeaderType     CMp3Misc::GetHeaderType() {return m_eHeaderType;}
  47. char* StrNStr(const char* str1,
  48.               const char* str2,
  49.               size_t depth1,
  50.               size_t depth2)
  51. {
  52.     const char *tracer1;
  53.     const char *tracer2;
  54.     size_t depth_tracer1;
  55.     size_t depth_tracer2;
  56.     while(*str1)
  57.     {
  58. for (tracer1 = str1, 
  59.      tracer2 = str2, 
  60.      depth_tracer1 = depth1, 
  61.      depth_tracer2 = depth2;
  62.      (*tracer1 == *tracer2) && depth_tracer1 && (*tracer1 != '');
  63.      tracer1++, depth_tracer1--)
  64. {
  65.     tracer2++;
  66.     depth_tracer2--;
  67.     if ((depth_tracer2 == 0) || (*tracer2 == ''))
  68.     {
  69. return (char *) str1;
  70.     }
  71. }
  72. if ((depth_tracer1 == 1) || (*tracer1 == ''))
  73. {
  74.     return NULL;
  75. }
  76. str1++;
  77. depth1--;
  78.     }
  79.     return NULL;
  80. }
  81. CMp3Misc::CMp3Misc()
  82.  :  m_pFmt(NULL)
  83.  ,  m_pTitle(NULL)
  84.  ,  m_pArtist(NULL)
  85.  ,  m_pAlbum(NULL)
  86.  ,  m_pYear(NULL)
  87.  ,  m_pGenre(NULL)
  88.  ,  m_nMetaOffset(0)
  89.  ,  m_nMetaRepeat(0)
  90.  ,  m_eHeaderType(eNone)
  91. {
  92.     PrepareString(m_pTitle);
  93.     PrepareString(m_pArtist);
  94.     PrepareString(m_pAlbum);
  95.     PrepareString(m_pYear);
  96.     PrepareString(m_pGenre);
  97. }
  98. CMp3Misc::~CMp3Misc()
  99. {
  100.     HX_VECTOR_DELETE(m_pTitle);
  101.     HX_VECTOR_DELETE(m_pArtist);
  102.     HX_VECTOR_DELETE(m_pAlbum);
  103.     HX_VECTOR_DELETE(m_pYear);
  104.     HX_VECTOR_DELETE(m_pGenre);
  105. }
  106. BOOL CMp3Misc::CheckForHeaders(UINT8 *pBuf,
  107.                                UINT32 dwSize,
  108.                                INT32 &lHeaderSize)
  109. {
  110.     BOOL    cRet = 1;
  111.     // Check for ID3v2 tags
  112.     UINT32 ulTag = (pBuf[0] << 16) |
  113.                    (pBuf[1] <<  8) |
  114.                     pBuf[2];
  115. #if defined(HELIX_FEATURE_MP3FF_LENIENT)
  116.     const char* pRIFF    = "RIFF";         // length 4
  117.     const char* pWAVE    = "WAVEfmt";      // length 7
  118.     const char* pData    = "data";         // length 4
  119. #endif /* #if defined(HELIX_FEATURE_MP3FF_LENIENT) */
  120.     if (ulTag == MP3_TAG_ID3)
  121.     {
  122.         m_eHeaderType = eID3v2;
  123.         lHeaderSize = GetTagLength(&pBuf[6], dwSize - 6) + 10;
  124.         GetId3v2Values(pBuf, dwSize, pBuf[3]);
  125.     }
  126.     // Check for ID3v1 tags
  127.     else if (ulTag == MP3_TAG_TAG)
  128.     {
  129.         m_eHeaderType = eID3v1;
  130.         GetId3v1Values(pBuf+3, dwSize-3);
  131.         lHeaderSize = -1;
  132.     }
  133. #if defined(HELIX_FEATURE_MP3FF_SHOUTCAST)
  134.     // Check for ShoutCast server files
  135.     else
  136.     if ( ulTag == MP3_TAG_ICY ||
  137.           StrNStr((const char*)pBuf,"icy-metaint", dwSize, 11)
  138.        )
  139.     {
  140.         const char* pFull    = "Server Full";  // length 11
  141.         const char* pICYMeta = "icy-metaint:"; // length 12
  142.         const char* pICYName = "icy-name:";    // length 9
  143.         m_eHeaderType = eShoutCast;
  144.         if (!memcmp(&pBuf[8], pFull, 11))
  145.         {
  146.             lHeaderSize = 0;
  147.         }
  148.         else
  149.         {
  150.             INT32 nSize = dwSize;
  151.             // Look for meta data repeat size
  152.             for (INT32 nTemp=0; nSize>=5; --nSize, ++nTemp)
  153.             {
  154.                 // If we find the end, set m_nMetaOffset and stop
  155.                 if (pBuf[nTemp] == 0x0D && pBuf[nTemp+1] == 0x0A) 
  156.                 {
  157.                      if (pBuf[nTemp+2] == 0x0D && pBuf[nTemp+3] == 0x0A)
  158.                      {
  159.                         m_nMetaOffset = nTemp + 4;
  160.                         break;
  161.                      }
  162.                      else if (pBuf[nTemp+3] == 0x0D && pBuf[nTemp+4] == 0x0A)
  163.                      {
  164.                         m_nMetaOffset = nTemp + 5;
  165.                         break;
  166.                      }
  167.                 }
  168.                 else 
  169.                 if (nSize > 12 &&
  170.                     !memcmp(&pBuf[nTemp],pICYMeta,12))
  171.                 {
  172.                     nTemp += 12;
  173.                     nSize -= 12;
  174.                     
  175.                     // Skip non-numubers
  176.                     while (nSize && (pBuf[nTemp] < 0x30 || pBuf[nTemp] > 0x39))
  177.                     {
  178.                         ++nTemp;
  179.                         --nSize;
  180.                     }                                    
  181.                     
  182.                     m_nMetaRepeat = atoi((const char*)&pBuf[nTemp]);
  183.                 
  184.                     // Find end of metaint data
  185.                     while (pBuf[nTemp+1] != 0x0A && nSize > 4)
  186.                     {
  187.                         ++nTemp;
  188.                         --nSize;
  189.                     }                                    
  190.                 }
  191.                 else
  192.                 if (nSize > 9 &&
  193.                     !memcmp(&pBuf[nTemp],pICYName,9))
  194.                 {
  195.                     UINT32 nTitle, nLen;
  196.                     nTemp += 9;
  197.                     nTitle = nTemp;
  198.                     
  199.                     while (pBuf[nTemp+1] != 0x0D && nSize > 4)
  200.                     {
  201.                         ++nTemp;
  202.                         --nSize;
  203.                     }
  204.                     
  205.                     // If the field is too INT32 for our buffer, truncate it.
  206.                     nLen = min(nTemp-nTitle+1, 256);
  207.                     dbcsStrCopy((char*)m_pTitle, (const char*)(pBuf+nTitle), nLen);
  208.                     
  209.                     // Skip 0x0A
  210.                     ++nTemp;
  211.                     --nSize;
  212.                 }
  213.             }
  214.             
  215.             HX_ASSERT(m_pFmt);
  216.             int nFrame = 0;
  217.             lHeaderSize = m_pFmt->ScanForSyncWord(pBuf, dwSize, nFrame);
  218.             if (lHeaderSize < 0)
  219.                 cRet = 0;
  220.         }
  221.     }
  222. #endif /* #if defined(HELIX_FEATURE_MP3FF_SHOUTCAST) */
  223. #if defined(HELIX_FEATURE_MP3FF_LENIENT)
  224.     // Check for bogus RIFFWav MP3s
  225.     else
  226.     if (!memcmp(pBuf,pRIFF,4) &&
  227.         !memcmp(&pBuf[8],pWAVE,7))
  228.     {
  229.         m_eHeaderType = eOther;
  230.         // Default value
  231.         lHeaderSize = 72;
  232.         // Search for the 'data' section of the RIFF file.
  233.         // The data is 8 bytes after it.
  234.         UINT8 *pTemp = pBuf;
  235.         while (dwSize >= 4)
  236.         {
  237.             if (!memcmp(pTemp,pData,4))
  238.             {
  239.                 lHeaderSize = pTemp - pBuf + 8;
  240.                 break;
  241.             }
  242.             else
  243.             {
  244.                 ++pTemp;
  245.                 --dwSize;
  246.             }
  247.         }
  248.     }
  249.     
  250.     // Check for bogus stuff
  251.     else if (ulTag == MP3_TAG_jpg ||
  252.              ulTag == MP3_TAG_bmp)
  253.     {
  254.         m_eHeaderType = eOther;
  255.         lHeaderSize = -1;
  256.     }
  257. #endif /* #if defined(HELIX_FEATURE_MP3FF_LENIENT) */
  258.     else
  259.     {
  260.         cRet = 0;
  261.         lHeaderSize = 0;
  262.     }
  263.     return cRet;
  264. }
  265. UINT8* CMp3Misc::GetId3Title(int &nLen)
  266. {
  267.     return GetId3String(m_pTitle, nLen);
  268. }
  269. UINT8* CMp3Misc::GetId3Artist(int &nLen)
  270. {
  271.     return GetId3String(m_pArtist, nLen);
  272. }
  273. UINT8* CMp3Misc::GetId3Album(int &nLen)
  274. {
  275.     return GetId3String(m_pAlbum, nLen);
  276. }
  277. UINT8* CMp3Misc::GetId3Genre(int &nLen)
  278. {
  279.     return GetId3String(m_pGenre, nLen);
  280. }
  281. UINT8* CMp3Misc::GetId3String(UINT8* pStr, int& nLen)
  282. {
  283.     nLen = 0;
  284.     if (!pStr)
  285.         return NULL;
  286.     nLen = strlen((const char*)pStr);
  287.     return pStr;
  288. }
  289. void CMp3Misc::PrepareString(UINT8*& rpStr)
  290. {
  291.     rpStr = new UINT8[257];
  292.     if (rpStr)
  293.         rpStr[0] = '';
  294. }
  295. void CMp3Misc::GetId3v1Values(UINT8 *pBuf,
  296.                                 UINT32 ulSize)
  297. {
  298.     // Get Title
  299.     GetId3EntryAndAdvance(m_pTitle, eTitleLen, pBuf, ulSize);
  300.     // Get Artist
  301.     GetId3EntryAndAdvance(m_pArtist, eArtistLen, pBuf, ulSize);
  302.     // Get Album
  303.     GetId3EntryAndAdvance(m_pAlbum, eAlbumLen, pBuf, ulSize);
  304. }
  305. void CMp3Misc::GetId3EntryAndAdvance(UINT8*  pStr,
  306.                                      UINT32  ulLen,
  307.                                      UINT8*& rpBuf,
  308.                                      UINT32& rulSize)
  309. {
  310.     if (rulSize >= ulLen)
  311.     {
  312.         GetId3Entry(rpBuf, pStr, ulLen);
  313.         rpBuf   += ulLen;
  314.         rulSize -= ulLen;
  315.     }
  316. }
  317. void CMp3Misc::GetId3Entry(UINT8 *pBuf,
  318.                            UINT8 *pEntry,
  319.                            int nEntryLen)
  320. {
  321.     dbcsStrCopy((char*)pEntry, (const char*)pBuf, nEntryLen);
  322. }
  323. void CMp3Misc::GetId3v2Values(UINT8 *pBuf,
  324.                               UINT32 ulSize,
  325.                               int nVersion)
  326. {
  327.     UINT32 count        = 0;
  328.     UINT32 tagLength    = 0;
  329.     UINT32 ulMinVer     = pBuf[3];
  330.     UINT32 ulNotDone    = 0x1F;
  331.     UINT8* ppStrArr[5]  = {m_pTitle,     m_pArtist,    m_pAlbum,     m_pYear,      m_pGenre};
  332.     UINT32 ulVer2Tag[5] = {MP3_TAG_TT2,  MP3_TAG_TP1,  MP3_TAG_TAL,  MP3_TAG_TYE,  MP3_TAG_TCO};
  333.     UINT32 ulVer3Tag[5] = {MP3_TAG_TIT2, MP3_TAG_TPE1, MP3_TAG_TALB, MP3_TAG_TYER, MP3_TAG_TCON};
  334.     if (ulMinVer == 2 || ulMinVer == 3)
  335.     {
  336.         // Get the tag lookup table
  337.         UINT32* pTag = (ulMinVer == 2 ? &ulVer2Tag[0] : &ulVer3Tag[0]);
  338.         // a tag's size is given in a 4-byte field of the following form:
  339.         // 0xxxxxxx0xxxxxxx0xxxxxxx0xxxxxxx where x is a value of 0 or 1
  340.         // the 0's are there to avoid potential sync problems
  341.         // this means we have bitshift in multiples of 7 rather than 8
  342.         tagLength = GetTagLength(&pBuf[count+6], ulSize - count - 6);
  343.         // tagLength gives the length of the tag from the point it's specified, so we need
  344.         // to add 10 to make it the total from the start of the file
  345.         count     += 10;
  346.         tagLength += 10;
  347.         tagLength  = min(tagLength, ulSize);
  348.         while (count < tagLength && ulNotDone)
  349.         {
  350.             // Create a 32-bit tag
  351.             UINT32 ulTag = (pBuf[count]   << 24) |
  352.                            (pBuf[count+1] << 16) |
  353.                            (pBuf[count+2] <<  8) |
  354.                             pBuf[count+3];
  355.             // If we are v3.2, then we only check three bytes
  356.             if (ulMinVer == 2) ulTag &= 0xFFFFFF00;
  357.             // Loop through and check for tags
  358.             for (UINT32 i = 0; i < 5; i++)
  359.             {
  360.                 if (ulTag == pTag[i])
  361.                 {
  362.                     if (ulMinVer == 2)
  363.                     {
  364.                         GetId3v2_2Entry(pBuf, ppStrArr[i], count);
  365.                     }
  366.                     else
  367.                     {
  368.                         GetId3v2_3Entry(pBuf, ppStrArr[i], count);
  369.                     }
  370.                     ulNotDone &= ~(1 << i);
  371.                     break;
  372.                 }
  373.             }
  374.             count++;
  375.         }
  376.     }
  377. }
  378. void CMp3Misc::GetId3v2_2Entry(UINT8 *pBuf,
  379.                                UINT8 *pEntry,
  380.                                UINT32 &count)
  381. {
  382.     // Data size is at byte 5 and includes the language encoding byte, so subtract one
  383.     // Data starts at byte 6 with lang byte, which we ignore
  384.     GetId3v2_XEntry(pBuf, pEntry, count, 5, 7, 6);
  385. }
  386. void CMp3Misc::GetId3v2_3Entry(UINT8 *pBuf,
  387.                                  UINT8 *pEntry,
  388.                                  UINT32 &count)
  389. {
  390.     // Data size is at byte 7 and includes the language encoding byte, so subtract one
  391.     // Data starts at byte 10 with lang byte, which we ignore
  392.     GetId3v2_XEntry(pBuf, pEntry, count, 7, 11, 10);
  393. }
  394. void CMp3Misc::GetId3v2_XEntry(UINT8* pBuf, UINT8* pEntry, UINT32& count,
  395.                                INT32 a, INT32 b, INT32 c)
  396. {
  397.     // Data size is at byte a and includes the language encoding byte, so subtract one
  398.     UINT8 nFieldLen = pBuf[count + a]-1;
  399.     // Data starts at byte c with lang byte, which we ignore
  400.     count += dbcsStrCopy((char*)pEntry, (const char*)(pBuf+count+b), nFieldLen) + c;
  401. }
  402. UINT32 CMp3Misc::GetTagLength(UINT8* pBuf, UINT32 ulLen)
  403. {
  404.     UINT32 ulRet = 0;
  405.     if (ulLen >= 4)
  406.     {
  407.         ulRet = ((pBuf[0] & 0x7F) << 21) +
  408.                 ((pBuf[1] & 0x7F) << 14) + 
  409.                 ((pBuf[2] & 0x7F) <<  7) +
  410.                  (pBuf[3] & 0x7F);
  411.     }
  412.     return ulRet;
  413. }