#include "cmetadatautilityitf.h"
#include <OpenMAXAL.h>
#include <string.h>
#include <ctype.h>
#include <uri8.h>
#include "profileutilmacro.h"
CMetadataUtilityItf::CMetadataUtilityItf():m_pS60Util(NULL), m_pHXUtil(NULL)
{
}
CMetadataUtilityItf::~CMetadataUtilityItf()
{
if(m_pS60Util)
{
delete m_pS60Util;
}
if(m_pHXUtil)
{
delete m_pHXUtil;
}
}
CMetadataUtilityItf* CMetadataUtilityItf::New(char* uri)
{
CMetadataUtilityItf* p_mdutilitf = new CMetadataUtilityItf;
TInt ret = p_mdutilitf->ParseSource(uri);
if(ret == KErrNone)
{
return p_mdutilitf;
}
delete p_mdutilitf;
return NULL;
}
TInt CMetadataUtilityItf::OpenSource(char* pOrigUri)
{
//Make a local copy for uri
if ( !pOrigUri )
return XA_RESULT_PARAMETER_INVALID;
int uriLen = strlen(pOrigUri);
char* uri = new char[uriLen+1];
if (! uri )
{
return XA_RESULT_MEMORY_FAILURE;
}
strncpy(uri, pOrigUri, uriLen);
uri[uriLen] = '\0';
////////////////////////////////////////////
_LIT8(KFileSlash,"file:///");
TInt fileslashlen = KFileSlash().Length();
TPtr8 fileuri((TUint8*)uri, strlen(uri),strlen(uri));
TPtr8 filepath = fileuri.RightTPtr(strlen(uri)-fileslashlen);
TInt pos = filepath.LocateReverse(':');
if(pos != KErrNotFound)
{
fileuri.Delete(fileslashlen+pos,1);
}
TUriParser8 localfileUri;
TInt ret = localfileUri.Parse(fileuri);
if(ret == KErrNone)
{
HBufC* file = NULL;
TRAP(ret,file = localfileUri.GetFileNameL());
if(ret == KErrNone)
{
if(m_pS60Util)
{
ret = m_pS60Util->ParseSource(*file);
}
else if(m_pHXUtil)
{
ret = m_pHXUtil->ParseSource(*file);
}
else
{
ret = KErrNotFound;
}
}
delete file;
}
if(uri)
{
delete []uri;
}
return ret;
}
TInt CMetadataUtilityItf::ExtractUCS2(TDesC& inDes, char* outPtr,TInt maxLen)
{
TPtrC tempPtr = inDes.Left((maxLen/2)-1); //save last one for null terminator
TInt outLen = tempPtr.Length() + 1;
TPtr16 outDes((unsigned short*)outPtr, outLen);
outDes.Copy(tempPtr);
outDes.ZeroTerminate();
return outLen * 2; //return size
}
TInt CMetadataUtilityItf::CalculateNumMetadataItems(TUint*numItems)
{
if(m_pS60Util)
{
return m_pS60Util->CalculateNumMetadataItems(numItems);
}
else
{
return m_pHXUtil->CalculateNumMetadataItems(numItems);
}
}
char* CMetadataUtilityItf::GetKey(TInt index)
{
if(m_pS60Util)
{
return m_pS60Util->GetKey(index);
}
else
{
return m_pHXUtil->GetKey(index);
}
}
TInt CMetadataUtilityItf::GetValueSize(TInt index)
{
if(m_pS60Util)
{
return m_pS60Util->GetValueSize(index);
}
else
{
return m_pHXUtil->GetValueSize(index);
}
}
TInt CMetadataUtilityItf::GetValue(TInt index, char* data, TInt maxLength, TInt* outSize, TInt* encodingType)
{
if(m_pS60Util)
{
return m_pS60Util->GetValue(index, data, maxLength, outSize, encodingType);
}
else
{
return m_pHXUtil->GetValue(index, data, maxLength, outSize, encodingType);
}
}
TInt CMetadataUtilityItf::ParseSource(char* uri)
{
char* tempPtr = NULL;
char extension[MAX_EXTENSION_SIZE] = { 0 };
tempPtr = strchr(uri, (int)'.');
strncpy(extension,tempPtr,sizeof(tempPtr));
for(unsigned int i=0;i<sizeof(extension);i++)
{
extension[i] = tolower(extension[i]);
}
//if s60 util in use
if(m_pS60Util)
{
//reset existing instace
TInt ret = m_pS60Util->Reset();
if(!CS60MetadataUtilityItf::IsSupportedExtension(extension))
{
delete m_pS60Util;
m_pS60Util = NULL;
}
}
if(m_pHXUtil)
{
//reset existing instace
TInt ret = m_pHXUtil->Reset();
if(CS60MetadataUtilityItf::IsSupportedExtension(extension))
{
delete m_pHXUtil;
m_pHXUtil = NULL;
}
}
if(!m_pS60Util && !m_pHXUtil)
{
if(CS60MetadataUtilityItf::IsSupportedExtension(extension))
{
m_pS60Util = CS60MetadataUtilityItf::New();
}
else
{
m_pHXUtil = CHXMetadataUtilityItf::New();
}
}
return OpenSource(uri);
}
bool CS60MetadataUtilityItf::IsSupportedExtension(char *extn)
{
if( (!strcasecmp(extn, ".mp3")) ||
(!strcasecmp(extn, ".wma")) ||
(!strcasecmp(extn, ".aac")) ||
(!strcasecmp(extn, ".wav")) ||
(!strcasecmp(extn, ".m4a")))
{
return true;
}
return false;
}
CS60MetadataUtilityItf* CS60MetadataUtilityItf::New()
{
CS60MetadataUtilityItf* self = new CS60MetadataUtilityItf();
TInt err = KErrGeneral;
TRAP(err, self->ConstructL());
if(err == KErrNone)
{
return self;
}
delete self;
return NULL;
}
CS60MetadataUtilityItf::CS60MetadataUtilityItf():pMetaDataUtility(NULL)
{
}
void CS60MetadataUtilityItf::ConstructL()
{
TAG_TIME_PROFILING_BEGIN;
pMetaDataUtility = CMetaDataUtility::NewL();
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
}
CS60MetadataUtilityItf::~CS60MetadataUtilityItf()
{
if(pMetaDataUtility)
{
TInt err = KErrGeneral;
TAG_TIME_PROFILING_BEGIN;
TRAP(err, pMetaDataUtility->ResetL());
delete pMetaDataUtility;
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
}
pMetaDataUtility = NULL;
}
TInt CS60MetadataUtilityItf::ParseSource(TDesC& fileName)
{
TInt err = KErrGeneral;
if(pMetaDataUtility)
{
TAG_TIME_PROFILING_BEGIN;
//open with the file handle
TRAP(err, pMetaDataUtility->OpenFileL(fileName));
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if(err == KErrNone)
{
uNumMetadataItems = pMetaDataUtility->MetaDataCount();
}
}
return err;
}
TInt CS60MetadataUtilityItf::CalculateNumMetadataItems(TUint* numItems)
{
TInt err = KErrGeneral;
if(pMetaDataUtility && numItems)
{
*numItems = uNumMetadataItems;
err = KErrNone;
}
return err;
}
char* CS60MetadataUtilityItf::KeyMapping(TMetaDataFieldId fldID)
{
switch(fldID)
{
case EMetaDataSongTitle:
{
return "KhronosTitle";
}
case EMetaDataArtist:
{
return "KhronosArtist";
}
case EMetaDataAlbum:
{
return "KhronosAlbum";
}
case EMetaDataYear:
{
return "KhronosYear";
}
case EMetaDataComment:
{
return "KhronosComment";
}
case EMetaDataAlbumTrack:
{
return "KhronosTrackNumber";
}
case EMetaDataGenre:
{
return "KhronosGenre";
}
case EMetaDataComposer:
{
return "Composer"; //Non Standard
}
case EMetaDataCopyright:
{
return "KhronosCopyright";
}
case EMetaDataOriginalArtist:
{
return "Original Artist"; //Non Standard
}
case EMetaDataUserUrl:
case EMetaDataUrl:
{
return "KhronosContentURL";
}
case EMetaDataJpeg:
{
return "attachedpicture";//"KhronosAlbumArtJPEG";
}
case EMetaDataVendor:
{
return "Vendor"; //Non Standard
}
case EMetaDataRating:
{
return "KhronosRating";
}
case EMetaDataDuration:
{
return "Duration"; //Non Standard
}
default:
{
}
}
return "UnSupported";
}
TInt CS60MetadataUtilityItf::ValueEncoding(TMetaDataFieldId fldID)
{
switch(fldID)
{
case EMetaDataJpeg:
{
return CMetadataUtilityItf::EBinaryEncoding;
}
case EMetaDataSongTitle:
case EMetaDataArtist:
case EMetaDataAlbum:
case EMetaDataYear:
case EMetaDataComment:
case EMetaDataAlbumTrack:
case EMetaDataGenre:
case EMetaDataComposer:
case EMetaDataCopyright:
case EMetaDataOriginalArtist:
case EMetaDataUserUrl:
case EMetaDataUrl:
case EMetaDataVendor:
case EMetaDataRating:
case EMetaDataDuration:
default:
{
return CMetadataUtilityItf::EUnicodeEncoding;
}
}
}
char* CS60MetadataUtilityItf::GetKey(TInt index)
{
if(pMetaDataUtility && index < uNumMetadataItems)
{
TMetaDataFieldId fieldId;
TAG_TIME_PROFILING_BEGIN;
TInt err = KErrGeneral;
TRAP(err, pMetaDataUtility->MetaDataFieldsL().FieldIdAt( index, fieldId ));
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if((err == KErrNone) && (fieldId != EUnknownMetaDataField))
{
return KeyMapping(fieldId);
}
}
return NULL;
}
TInt CS60MetadataUtilityItf::GetValueSize(TInt index)
{
if(pMetaDataUtility && index < uNumMetadataItems)
{
TMetaDataFieldId fieldId;
TInt err = KErrGeneral;
TRAP(err, pMetaDataUtility->MetaDataFieldsL().FieldIdAt( index, fieldId ));
if((err == KErrNone) && (fieldId != EUnknownMetaDataField))
{
const CMetaDataFieldContainer* iContainer = NULL;
TRAP(err, iContainer = &pMetaDataUtility->MetaDataFieldsL());
if(err == KErrNone)
{
if(ValueEncoding(fieldId) == CMetadataUtilityItf::EUnicodeEncoding)
{
TPtrC field = iContainer->Field( fieldId );
if(field != KNullDesC)
{
return field.Size() + 2; //additional character (two bytes) for null terminator
}
}
else //Binary
{
TPtrC8 field8 = iContainer->Field8( fieldId );
if(field8 != KNullDesC8)
{
return field8.Size();
}
}
}
}
}
return 0;
}
TInt CS60MetadataUtilityItf::GetValue(TInt index, char* data, TInt maxLength, //in params
TInt* outSize, TInt* encodingType) //out params
{
TInt retValueSize = 0;
*encodingType= CMetadataUtilityItf::EUnknownEncoding;
if(pMetaDataUtility && index < uNumMetadataItems)
{
TMetaDataFieldId fieldId;
TInt err = KErrGeneral;
TRAP(err, pMetaDataUtility->MetaDataFieldsL().FieldIdAt( index, fieldId ));
if((err==KErrNone) && (fieldId != EUnknownMetaDataField))
{
const CMetaDataFieldContainer* iContainer = NULL;
TRAP(err, iContainer = &pMetaDataUtility->MetaDataFieldsL());
if(err == KErrNone)
{
*encodingType = ValueEncoding(fieldId);
if(*encodingType == CMetadataUtilityItf::EUnicodeEncoding)
{
TAG_TIME_PROFILING_BEGIN;
TPtrC field = iContainer->Field( fieldId );
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if(field != KNullDesC)
{
*outSize = CMetadataUtilityItf::ExtractUCS2(field, data, maxLength);
retValueSize = field.Size() + 2; //actual size
}
}
else //Binary
{
TAG_TIME_PROFILING_BEGIN;
TPtrC8 field8 = iContainer->Field8( fieldId );
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if(field8 != KNullDesC8)
{
*outSize = (maxLength > field8.Size())?field8.Size():maxLength;
memcpy(data, field8.Ptr(), *outSize);
retValueSize = field8.Size();
}
}
}
}
}
return retValueSize;
}
TInt CS60MetadataUtilityItf::Reset()
{
TInt err = KErrNone;
if(pMetaDataUtility)
{
TRAP(err, pMetaDataUtility->ResetL());
}
return err;
}
CHXMetadataUtilityItf::CHXMetadataUtilityItf():pHXMetaDataUtility(NULL)
{
}
void CHXMetadataUtilityItf::ConstructL()
{
TAG_TIME_PROFILING_BEGIN;
pHXMetaDataUtility = CHXMetaDataUtility::NewL();
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
}
CHXMetadataUtilityItf* CHXMetadataUtilityItf::New()
{
CHXMetadataUtilityItf* self = new CHXMetadataUtilityItf();
if(self)
{
TInt err = KErrGeneral;
TRAP(err, self->ConstructL());
if(err != KErrNone)
{
delete self;
self = NULL;
}
}
return self;
}
CHXMetadataUtilityItf::~CHXMetadataUtilityItf()
{
if(pHXMetaDataUtility)
{
TInt err = KErrGeneral;
TAG_TIME_PROFILING_BEGIN;
TRAP(err, pHXMetaDataUtility->ResetL());
delete pHXMetaDataUtility;
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
}
pHXMetaDataUtility = NULL;
}
TInt CHXMetadataUtilityItf::Reset()
{
TInt err = KErrNone;
if(pHXMetaDataUtility)
{
TRAP(err, pHXMetaDataUtility->ResetL());
}
return err;
}
TInt CHXMetadataUtilityItf::ParseSource(TDesC& fileName)
{
TInt err = KErrGeneral;
if(pHXMetaDataUtility)
{
//open with the file handle
TAG_TIME_PROFILING_BEGIN;
TRAP(err, pHXMetaDataUtility->OpenFileL(fileName));
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if(err == KErrNone)
{
return pHXMetaDataUtility->GetMetaDataCount(uNumMetadataItems);
}
}
return err;
}
TInt CHXMetadataUtilityItf::CalculateNumMetadataItems(TUint* numItems)
{
TInt err = KErrGeneral;
if(pHXMetaDataUtility && numItems)
{
*numItems = uNumMetadataItems;
err = KErrNone;
}
return err;
}
char* CHXMetadataUtilityItf::KeyMapping(HXMetaDataKeys::EHXMetaDataId fldID)
{
switch(fldID)
{
case HXMetaDataKeys::EHXTitle:
{
return "KhronosTitle";
}
case HXMetaDataKeys::EHXPerformer:
{
return "KhronosArtist";
}
case HXMetaDataKeys::EHXDescription:
{
return "KhronosComment";
}
case HXMetaDataKeys::EHXGenre:
{
return "KhronosGenre";
}
case HXMetaDataKeys::EHXAuthor:
{
return "Composer"; //Non Standard
}
case HXMetaDataKeys::EHXCopyright:
{
return "KhronosCopyright";
}
case HXMetaDataKeys::EHXContentURI:
{
return "KhronosContentURL";
}
case HXMetaDataKeys::EHXDuration:
{
return "Duration"; //Non Standard
}
case HXMetaDataKeys::EHXClipBitRate:
{
return "ClipBitRate"; //non-standard
}
case HXMetaDataKeys::EHXVideoBitRate:
{
return "VideoBitRate"; // non-standard
}
case HXMetaDataKeys::EHXAudioBitRate:
{
return "AudioBitRate";
}
case HXMetaDataKeys::EHXCodec:
{
return "Codec";
}
case HXMetaDataKeys::EHXFrameSize:
{
return "Resolution";
}
case HXMetaDataKeys::EHXFramesPerSecond:
{
return "FrameRate";
}
case HXMetaDataKeys::EHXStreamCount:
{
return "Stream Count";
}
case HXMetaDataKeys::EHXLiveStream:
{
return "Live Stream";
}
case HXMetaDataKeys::EHXSeekable:
{
return "Seekable";
}
case HXMetaDataKeys::EHXContentType:
{
return "Content Type";
}
case HXMetaDataKeys::EHXFormat:
{
return "Format";
}
case HXMetaDataKeys::EHXQuality:
{
return "Quality";
}
case HXMetaDataKeys::EHXAbstract:
{
return "Abstract";
}
case HXMetaDataKeys::EHXMimeType:
{
return "MimeType";
}
case HXMetaDataKeys::EHXIconURI:
{
return "Icon URI";
}
case HXMetaDataKeys::EHXEPreviewURI:
{
return "Preview URI";
}
case HXMetaDataKeys::EHXContentID:
{
return "Content ID";
}
case HXMetaDataKeys::EHXInfoURL:
{
return "Info URL";
}
default:
{
}
}
return "UnSupported";
}
TInt CHXMetadataUtilityItf::ValueEncoding(HXMetaDataKeys::EHXMetaDataId fldID)
{
switch(fldID)
{
default:
{
return CMetadataUtilityItf::EUnicodeEncoding;
}
}
}
char* CHXMetadataUtilityItf::GetKey(TInt index)
{
if(pHXMetaDataUtility && index < uNumMetadataItems)
{
HXMetaDataKeys::EHXMetaDataId id;
HBufC* pDes;
TAG_TIME_PROFILING_BEGIN;
TInt err = pHXMetaDataUtility->GetMetaDataAt(index, id, pDes);
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
if(err == KErrNone)
{
return KeyMapping(id);
}
}
return NULL;
}
TInt CHXMetadataUtilityItf::GetValueSize(TInt index)
{
if(pHXMetaDataUtility && index < uNumMetadataItems)
{
HXMetaDataKeys::EHXMetaDataId id;
HBufC* pDes;
TInt err = pHXMetaDataUtility->GetMetaDataAt(index, id, pDes);
if(err == KErrNone)
{
if(ValueEncoding(id) == CMetadataUtilityItf::EUnicodeEncoding)
{
return pDes->Size() + 2; //additional character (two bytes) for null terminator
}
else //Binary
{
//no support
}
}
}
return 0;
}
TInt CHXMetadataUtilityItf::GetValue(TInt index, char* data, TInt maxLength, //in params
TInt* outSize, TInt* encodingType) //out params
{
TInt retValueSize = 0;
*encodingType= CMetadataUtilityItf::EUnknownEncoding;
if(pHXMetaDataUtility && index < uNumMetadataItems)
{
HXMetaDataKeys::EHXMetaDataId id;
HBufC* pDes;
TAG_TIME_PROFILING_BEGIN;
TInt err = pHXMetaDataUtility->GetMetaDataAt(index, id, pDes);
TAG_TIME_PROFILING_END;
PRINT_TO_CONSOLE_TIME_DIFF;
*encodingType = ValueEncoding(id);
if(err == KErrNone)
{
if(*encodingType == CMetadataUtilityItf::EUnicodeEncoding)
{
*outSize = CMetadataUtilityItf::ExtractUCS2(*pDes, data, maxLength);
retValueSize = pDes->Size() + 2; //actual Size
}
else //Binary
{
//no support
}
}
}
return retValueSize;
}
extern "C" {
void* mmf_metadata_utility_init(char* uri)
{
return CMetadataUtilityItf::New(uri);
}
void mmf_metadata_utility_destroy(void* context)
{
delete ((CMetadataUtilityItf*)context);
}
XAresult mmf_metadata_utility_parse_source(void* context, char* uri)
{
TInt err = ((CMetadataUtilityItf*)context)->ParseSource(uri);
if(err == KErrNone)
{
return XA_RESULT_SUCCESS;
}
return XA_RESULT_PARAMETER_INVALID;
}
XAresult mmf_get_item_count(void* context, XAuint32* itemCount)
{
if(itemCount)
{
TInt err = ((CMetadataUtilityItf*)(context))->CalculateNumMetadataItems((TUint *)itemCount);
if(err == KErrNone)
{
return XA_RESULT_SUCCESS;
}
}
return XA_RESULT_PARAMETER_INVALID;
}
XAresult mmf_get_key_size(void* context, XAuint32 keyIndex, XAuint32* keySize)
{
char* key = ((CMetadataUtilityItf*)(context))->GetKey(keyIndex);
if(key && keySize)
{
*keySize = (strlen(key) + sizeof(XAMetadataInfo));
return XA_RESULT_SUCCESS;
}
return XA_RESULT_PARAMETER_INVALID;
}
XAresult mmf_get_key(void* context, XAuint32 index,XAuint32 keySize, XAMetadataInfo *pKey)
{
XAresult ret = XA_RESULT_PARAMETER_INVALID;
TInt keyDataSize = keySize - sizeof(XAMetadataInfo) + 1;
char* ascKey = ((CMetadataUtilityItf*)(context))->GetKey(index);
if(ascKey && keyDataSize)
{
TInt ascKeySize = strlen(ascKey);
TInt outSize = (ascKeySize >= keyDataSize) ? (keyDataSize - 1) : ascKeySize;
pKey->size = outSize + 1;
pKey->encoding = XA_CHARACTERENCODING_ASCII;
strcpy((char *)(pKey->langCountry), "en-us");
strncpy((char *)(pKey->data), ascKey, outSize);
pKey->data[outSize] = '\0';
if(ascKeySize >= keyDataSize)
{
ret = XA_RESULT_BUFFER_INSUFFICIENT;
}
else
{
ret = XA_RESULT_SUCCESS;
}
}
ret = XA_RESULT_SUCCESS;
return ret;
}
XAresult mmf_get_value_size(void* context, XAuint32 index, XAuint32 *pValueSize)
{
if(pValueSize)
{
*pValueSize = ((CMetadataUtilityItf*)(context))->GetValueSize(index) + sizeof(XAMetadataInfo) - 1; //XAMetadataInfo already includes one byte for Data
return XA_RESULT_SUCCESS;
}
return XA_RESULT_PARAMETER_INVALID;
}
XAresult mmf_get_value(void* context, XAuint32 index, XAuint32 valueSize, XAMetadataInfo *pValue)
{
XAresult ret = XA_RESULT_PARAMETER_INVALID;
TInt dataSize = valueSize - sizeof(XAMetadataInfo) + 1;
TInt outLen = 0, encodingType = CMetadataUtilityItf::EUnknownEncoding;
if(dataSize > 0)
{
TInt actualDataSize = ((CMetadataUtilityItf*)(context))->GetValue(index, (char*)pValue->data, dataSize, &outLen, &encodingType);
pValue->size = outLen;
pValue->encoding = (encodingType == CMetadataUtilityItf::EUnicodeEncoding) ? XA_CHARACTERENCODING_UTF16LE : XA_CHARACTERENCODING_BINARY;
strcpy((char *)(pValue->langCountry), "en-us");
if(!actualDataSize)
{
return XA_RESULT_INTERNAL_ERROR;
}
if(actualDataSize > dataSize)
{
ret = XA_RESULT_BUFFER_INSUFFICIENT;
}
else
{
ret = XA_RESULT_SUCCESS;
}
}
return ret;
}
}