[Player-cvs] music/librarykit mmp_library.cpp, 1.3, 1.4 mmp_library_playqueue.cpp, 1.1.1.1, 1.2

[Player-cvs] music/librarykit mmp_library.cpp, 1.3, 1.4 mmp_library_playqueue.cpp, 1.1.1.1, 1.2

bnewman at helixcommunity.org bnewman at helixcommunity.org
Mon Jul 19 15:35:04 PDT 2004


Update of /cvsroot/player/music/librarykit
In directory cvs-new:/tmp/cvs-serv9431

Modified Files:
	mmp_library.cpp mmp_library_playqueue.cpp 
Log Message:
Fixed play queue bug (Track 3 of 1 problem)
Added code to parse m4a file tags.
CRd by crobinson.


Index: mmp_library_playqueue.cpp
===================================================================
RCS file: /cvsroot/player/music/librarykit/mmp_library_playqueue.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mmp_library_playqueue.cpp	1 Jun 2004 23:47:05 -0000	1.1.1.1
+++ mmp_library_playqueue.cpp	19 Jul 2004 22:35:02 -0000	1.2
@@ -73,32 +73,37 @@
 {
     m_Queue.AddTail(pTrack);
 
-    if (m_CurrentTrack == NULL)
-    {
-	m_CurrentTrack = m_Queue.GetTailPosition();
-    }
+    m_CurrentTrack = m_Queue.GetTailPosition();
 }
 
 void
 CMmpLibraryPlayQueue::GetNextTrack(CMmpTrack*& pTrack)
-{
-    if (!m_Queue.IsEmpty() && m_CurrentTrack)
-    {
-	pTrack = (CMmpTrack*)m_Queue.GetNext(m_CurrentTrack);
-
-	if (!m_CurrentTrack && m_bLoop)
-	{
-	    m_CurrentTrackNum = 0;
-	    m_CurrentTrack = m_Queue.GetHeadPosition();
-	    pTrack = (CMmpTrack*)m_Queue.GetNext(m_CurrentTrack);
-	}
-
-	++m_CurrentTrackNum;
-    }
-    else
-    {
-	pTrack = NULL;
-    }
+{
+    if (!m_Queue.IsEmpty() && m_CurrentTrack)
+    {
+	pTrack = (CMmpTrack*)m_Queue.GetAtNext(m_CurrentTrack);
+
+	if (!m_CurrentTrack && m_bLoop)
+	{
+	    m_CurrentTrackNum = 1;
+	    m_CurrentTrack = m_Queue.GetHeadPosition();
+	    pTrack = (CMmpTrack*)m_Queue.GetAt(m_CurrentTrack);
+	}
+	else if (!m_CurrentTrack)
+	{
+	    m_CurrentTrackNum = m_Queue.GetCount();
+	    m_CurrentTrack = m_Queue.GetTailPosition();
+	    pTrack = (CMmpTrack*)m_Queue.GetAt(m_CurrentTrack);
+	}
+	else
+	{
+	    ++m_CurrentTrackNum;
+	}
+    }
+    else
+    {
+	pTrack = NULL;
+    }
 }
 
 void
@@ -112,10 +117,18 @@
 	{
 	    m_CurrentTrackNum = m_Queue.GetCount();
 	    m_CurrentTrack = m_Queue.GetTailPosition();
-	    pTrack = (CMmpTrack*)m_Queue.GetNext(m_CurrentTrack);
+	    pTrack = (CMmpTrack*)m_Queue.GetAt(m_CurrentTrack);
+	}
+	else if (!m_CurrentTrack)
+	{
+	    m_CurrentTrackNum = 1;
+	    m_CurrentTrack = m_Queue.GetHeadPosition();
+	    pTrack = (CMmpTrack*)m_Queue.GetAt(m_CurrentTrack);
+	}
+	else
+	{
+	    --m_CurrentTrackNum;
 	}
-
-	--m_CurrentTrackNum;
     }
     else
     {

Index: mmp_library.cpp
===================================================================
RCS file: /cvsroot/player/music/librarykit/mmp_library.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mmp_library.cpp	9 Jul 2004 00:08:37 -0000	1.3
+++ mmp_library.cpp	19 Jul 2004 22:35:02 -0000	1.4
@@ -36,9 +36,12 @@
 #include "mmp_library.h"
 #include "mmp_library_track.h"
 #include "mmp_library_id3v1.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
 
 //
-// Metadata defines 
+// RJMD Metadata defines 
 //
 
 #define MD_RIFF_FOURCC HX_FOURCC('R','M','M','D')
@@ -49,7 +52,27 @@
 #define RMMD_BIN_VERSION sizeof(UINT32)
 #define RMMD_BIN_MDSIZE RMMD_BIN_VERSION+sizeof(UINT32)
 #define RMMD_BIN_STATIC_SIZE sizeof(UINT32)*3
-
+
+//
+// M4A Tag Defines
+//
+ 
+#define GETUINT32(pbByte) ( (pbByte[0] << 24) + ((pbByte[1]& 0xff) << 16) + ((pbByte[2]& 0xff) << 8) + (pbByte[3] & 0xff) )
+#define SIZE_DATASIZE		4
+#define ATOM_IDSIZE		4
+#define SIZE_MODIFIER		4
+#define SIZE_DATATYPE		4
+#define MP4_BUILD_ATOMID(a,b,c,d) ( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+
+const char* kudta = "udta";
+const char* kmeta = "meta";
+const char* kilst = "ilst";
+const char* kVersionedAtomNames[] = 
+{
+    "meta"
+    ,"mvhd"
+    ,""
+};
 
 CMmpLibrary::CMmpLibrary()
 {
@@ -386,7 +409,186 @@
 exit:
     return res;
 }
-
+
+BOOL 
+CMmpLibrary::IsVersionedM4aAtom(const char* szAtomName)
+{
+    const char** pszName = kVersionedAtomNames;
+
+    while(strlen(*pszName))
+    {
+	if(!stricmp(szAtomName, *pszName))
+	    return TRUE;
+
+	pszName++;
+    }
+
+    return FALSE;
+}
+
+BOOL 
+CMmpLibrary::FillM4aNamedAtomSturcture(const char *szName, 
+			    UINT32 nParentAtomOffset, 
+			    BOOL bParentAtomVersioned, 
+			    M4aAtomSizeAndOffset &atomStruct, 
+			    BYTE* pByteData, 
+			    UINT32 uDataSize)
+{
+    BOOL bFound = FALSE;
+    UINT32 nStartAtOffset = nParentAtomOffset + ATOM_IDSIZE + SIZE_DATASIZE;
+    if(bParentAtomVersioned)
+    {
+	nStartAtOffset += SIZE_DATASIZE;
+    }
+    BYTE* pbByte = pByteData + nStartAtOffset;
+    BYTE* pbEnd = pByteData + uDataSize;
+
+    if(!pbByte)
+	return bFound;
+
+    
+    UINT32 uAtomSize = 0;
+    BOOL bVersionedAtom = FALSE;
+    while( !bFound && (pbByte < pbEnd) )
+    {
+	uAtomSize = 0;
+	bVersionedAtom = FALSE;
+
+	char szAtomName[ATOM_IDSIZE + 1];
+	memset(szAtomName, 0, sizeof(szAtomName));
+	uAtomSize = GETUINT32(pbByte);
+
+	szAtomName[0] = pbByte[SIZE_DATASIZE];
+	szAtomName[1] = pbByte[SIZE_DATASIZE + 1];
+	szAtomName[2] = pbByte[SIZE_DATASIZE + 2];
+	szAtomName[3] = pbByte[SIZE_DATASIZE + 3];
+
+	if(!stricmp(szAtomName, szName))
+	{
+	    bVersionedAtom = IsVersionedM4aAtom(szAtomName);
+	    bFound = TRUE;
+	}
+	else
+	{
+	    if(uAtomSize == 0)
+		pbByte += SIZE_DATASIZE;
+	    else
+		pbByte += uAtomSize;
+	}
+    }
+
+    if(bFound)
+    {
+	atomStruct.nDataSize = uAtomSize;
+	atomStruct.nOffset = pbByte - pByteData;
+	atomStruct.bIsVersioned = bVersionedAtom;
+    }
+
+    return bFound;
+}
+
+HX_RESULT 
+CMmpLibrary::GetM4aMetaData(M4aAtomSizeAndOffset ilstAtomStruct,
+			    BYTE* pByteData,
+			    UINT32 itemId) 
+{
+    HX_RESULT res = HXR_FAIL;
+
+    UINT32 nStartAtOffset = ilstAtomStruct.nOffset + ATOM_IDSIZE + SIZE_DATASIZE;
+    BYTE* pbByte = pByteData + nStartAtOffset;
+    BYTE* pbEnd = pByteData + ilstAtomStruct.nOffset + ilstAtomStruct.nDataSize;
+
+    if(!pbByte)
+	return res;
+
+    UINT32 uAtomSize = 0;
+    while(pbByte < pbEnd)
+    {
+	char szAtomName[ATOM_IDSIZE + 1];
+	memset(szAtomName, 0, sizeof(szAtomName));
+	uAtomSize = GETUINT32(pbByte);
+
+	szAtomName[0] = pbByte[SIZE_DATASIZE];
+	szAtomName[1] = pbByte[SIZE_DATASIZE + 1];
+	szAtomName[2] = pbByte[SIZE_DATASIZE + 2];
+	szAtomName[3] = pbByte[SIZE_DATASIZE + 3];
+
+	if(strlen(szAtomName))
+	{
+	    if(uAtomSize == 0)
+	    {
+		break;
+	    }
+	    else
+	    {
+		UINT32 atomId = MP4_BUILD_ATOMID(szAtomName[0], szAtomName[1], szAtomName[2], szAtomName[3]);
+
+		// get atom data .. fill in the atom class structure ...  and add to array.
+		BYTE* pData = pbByte + SIZE_DATASIZE + ATOM_IDSIZE + SIZE_DATASIZE + ATOM_IDSIZE;
+
+		UINT32 uDataType = GETUINT32(pData);
+		pData += SIZE_DATATYPE;
+		
+		UINT32 uDataModifier = GETUINT32(pData);
+		pData += SIZE_MODIFIER;
+
+		UINT32 nDataSize = pbByte + uAtomSize - pData;
+
+		if (atomId == MP4_BUILD_ATOMID(0xA9,'A','R','T'))
+		{
+		    res = SetItemTagData(itemId,
+					 CMmpLibrary::ETagArtist,
+					 nDataSize,
+					 pData);
+		}
+		else if (atomId == MP4_BUILD_ATOMID(0xA9,'a','l','b'))
+		{
+		    res = SetItemTagData(itemId,
+					 CMmpLibrary::ETagAlbum,
+					 nDataSize,
+					 pData);
+		}
+		else if (atomId == MP4_BUILD_ATOMID(0xA9,'n','a','m'))
+		{
+		    res = SetItemTagData(itemId,
+					 CMmpLibrary::ETagName,
+					 nDataSize,
+					 pData);
+		}
+		else if (atomId == MP4_BUILD_ATOMID('t','r','k','n'))
+		{
+
+		    UINT32 id;
+		    char binBuf[4];
+		    id = pData[3] | (pData[2] << 8) | (pData[1] << 16) | (pData[0] << 24); 
+		    sprintf(binBuf, "%d", id);
+		    res = SetItemTagData(itemId,
+				 CMmpLibrary::ETagTrackNum,
+				 strlen(binBuf),
+				 binBuf);
+		}
+		else if (atomId == MP4_BUILD_ATOMID(0xA9,'g','e','n'))
+		{
+		    res = SetItemTagData(itemId,
+					 CMmpLibrary::ETagGenre,
+					 nDataSize,
+					 pData);
+
+		}
+
+		pbByte += uAtomSize;
+	    }
+
+	    uAtomSize = 0;
+	}
+	else
+	{
+	    break;
+	}
+    }
+
+    return res;
+}
 
 void 
 CMmpLibrary::ExtractMetaData(const char* pFilename)
@@ -400,7 +602,10 @@
 
 	UINT32 nRJMDBufSize = 0;
 
-	// First, see if there is an RJMD buffer in the file
+	//
+	// First, see if there is an RJMD Tag in the file
+	//
+	
 	if (GetRJMDOffsetFromEnd(pFile, &m_ulOrigOffset, &nRJMDBufSize) == HXR_OK)
 	{
 	    char* pRJMDTag = FindRJMDTag(pFile, m_ulOrigOffset, nRJMDBufSize);
@@ -426,7 +631,11 @@
 		HX_VECTOR_DELETE(pRJMDTag);
 	    }
 	}
-
+
+	//
+	// If not there, check for ID3 Tag
+	//
+	
 	if (res != HXR_OK)
 	{
 	    char* pId3V1Tag = FindId3V1Tag(pFile);
@@ -436,7 +645,27 @@
 		res = AddItemFromId3V1Tag(pId3V1Tag, itemId);
 		HX_VECTOR_DELETE(pId3V1Tag);
 	    }
-	}
+	}
+
+	//
+	// Last try - check for M4A (AAC) Tag
+	//
+	
+	if (res != HXR_OK)
+	{
+	    UINT32 uDataSize;
+	    struct stat buf;
+	    stat(pFilename, &buf);
+
+	    BYTE* pMoovTag = FindM4aTag(pFile, buf.st_size, uDataSize);
+
+	    if (pMoovTag)
+	    {
+		res = AddItemFromM4aTag(pMoovTag, uDataSize, itemId);
+		HX_VECTOR_DELETE(pMoovTag);
+	    }
+	}
+
 
 	if (HXR_OK == res)
 	{
@@ -488,6 +717,62 @@
     delete [] pReadBuf;
     return NULL;
 }
+
+BYTE*
+CMmpLibrary::FindM4aTag(FILE* pFile, UINT32 uFileSize, UINT32& uDataSize)
+{
+    char sAtom[ATOM_IDSIZE + SIZE_DATASIZE + 1];
+    BOOL bMoovFound = FALSE;
+    BYTE* byteData = NULL;
+
+    fseek(pFile, 0, SEEK_SET);
+
+    while(!bMoovFound && !feof(pFile))
+    {
+	memset(sAtom, 0, ATOM_IDSIZE + SIZE_DATASIZE + 1);
+	fread(sAtom, sizeof(sAtom) - 1, 1, pFile);
+
+	uDataSize = GETUINT32(sAtom);
+
+	char* szAtomName = &(sAtom[4]);
+	if((stricmp(szAtomName, "moov") == 0) ||
+	   (stricmp(szAtomName, "free") == 0))
+	{
+	    bMoovFound = TRUE;
+	    fseek(pFile, -1*(long)sizeof(sAtom) + 1, SEEK_CUR);
+	}
+	else
+	{
+	    if ((uDataSize < sizeof(sAtom)) || (uDataSize > uFileSize))
+	    {
+		// not found... Either no metadata or invalid file
+		break;
+	    }
+	    fseek(pFile, uDataSize - sizeof(sAtom) + 1, SEEK_CUR);
+	    uDataSize = 0;
+	}
+    }
+
+    if(bMoovFound && uDataSize)
+    {	    
+	byteData = new BYTE[uDataSize];
+
+	if(byteData)
+	{
+	    if (uDataSize != fread(byteData, 1, uDataSize, pFile))
+	    {
+		uDataSize = 0;
+		HX_VECTOR_DELETE(byteData);
+	    }
+	}
+	else
+	{
+	    uDataSize = 0;
+	}
+    }
+
+    return byteData;
+}
 
 HX_RESULT
 CMmpLibrary::AddItemFromId3V1Tag(const char* pId3V1Tag, UINT32& itemId)
@@ -775,5 +1060,59 @@
     return res;
 }
 
-
+HX_RESULT
+CMmpLibrary::AddItemFromM4aTag(BYTE* pMoovTag, UINT32 uDataSize, UINT32& itemId)
+{
+    HX_RESULT res = HXR_FAIL;
+
+    M4aAtomSizeAndOffset m_moovAtomStructure;
+    M4aAtomSizeAndOffset m_udtaAtomStructure;
+    M4aAtomSizeAndOffset m_metaAtomStructure;
+    M4aAtomSizeAndOffset m_ilstAtomStructure;
+		    
+    m_moovAtomStructure.nDataSize = 0;
+    m_moovAtomStructure.nOffset = 0;
+    m_moovAtomStructure.bIsVersioned = FALSE;
+
+    m_udtaAtomStructure.nDataSize = 0;;
+    m_udtaAtomStructure.nOffset = 0;
+    m_udtaAtomStructure.bIsVersioned = FALSE;
+
+    m_metaAtomStructure.nDataSize = 0;;
+    m_metaAtomStructure.nOffset = 0;
+    m_metaAtomStructure.bIsVersioned = FALSE;
+
+    m_ilstAtomStructure.nDataSize = 0;
+    m_ilstAtomStructure.nOffset = 0;
+    m_ilstAtomStructure.bIsVersioned = FALSE;
+
+    m_moovAtomStructure.nDataSize = uDataSize;
+    m_moovAtomStructure.nOffset = 0;
+    m_moovAtomStructure.bIsVersioned = FALSE;
+
+    if(FillM4aNamedAtomSturcture(kudta, m_moovAtomStructure.nOffset, m_moovAtomStructure.bIsVersioned, m_udtaAtomStructure, pMoovTag, uDataSize))
+    {
+	if(FillM4aNamedAtomSturcture(kmeta, m_udtaAtomStructure.nOffset, m_udtaAtomStructure.bIsVersioned, m_metaAtomStructure, pMoovTag, uDataSize))
+	{
+	    if(FillM4aNamedAtomSturcture(kilst, m_metaAtomStructure.nOffset, m_metaAtomStructure.bIsVersioned, m_ilstAtomStructure, pMoovTag, uDataSize))
+	    {
+		res = AddItem(itemId);
+
+		if (HXR_OK == res)
+		{
+		    res = SetItemTagData(itemId,
+					 CMmpLibrary::ETagTrackRecord, 
+					 0, NULL);
+		}
+
+		if (HXR_OK == res)
+		{
+		    res = GetM4aMetaData(m_ilstAtomStructure, pMoovTag, itemId);
+		}
+	    }
+	}
+    }
+
+    return res;
+}
 




More information about the Player-cvs mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.