www.pudn.com > LECTEUR-MP3.zip > RepExplorer.cpp


/************************************************************** 
**********  RepExplorer fait par kt_system (12/2007) ********** 
***************************************************************/ 
/* 
26 Mai 2008 : Modification du ConstructTree pour qui recherche chaque sous-dossier et modification du FindFile pour qui recherche chaque fichier dans chaque sous-dossier 
 
Version 1.0 
	 
	  - Gestion basique des dossiers 
	  - Methode d'ajout, modif suppression de fichier 
	  - Systeme simple de filtrage des fichiers (par extension) 
	  - Systeme simple de recherche de dossier ou fichier 
 
Version 1.1 
 
	  - Correction de quelques Bugs 
	  - Ajout de la classe abstraite CAudioFile 
	  - Ajout de la classe CMp3File 
 
*/ 
 
#include "stdafx.h" 
#include "MusGest.h" 
#include "RepExplorer.h" 
#include "fmod.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
 
/************************************************************************** 
****************************  CRepExplorer  ******************************* 
***************************************************************************/ 
 
//------------------------------------------------------------------------- 
CRepExplorer::CRepExplorer() 
{ 
	m_pRootRep = NULL; 
	m_bUseFilter = false; 
} 
 
//------------------------------------------------------------------------- 
CRepExplorer::CRepExplorer(CString strRootPath) 
{ 
	m_pRootRep = NULL; 
	ConstructTree(strRootPath, false); 
} 
 
//------------------------------------------------------------------------- 
CRepExplorer::~CRepExplorer() 
{ 
	if (m_pRootRep) 
		delete m_pRootRep; 
 
	m_pRootRep = NULL; 
} 
 
//------------------------------------------------------------------------- 
bool CRepExplorer::ConstructTree(CString strRootPath,bool bOnlyFolderDetect /*= false*/) 
{ 
	m_strRootPath = strRootPath; 
	m_bOnlyFolderDetect = bOnlyFolderDetect; 
 
	if (m_pRootRep) 
		delete m_pRootRep; 
 
	//Construit le premier rep 
	//(Fct recursive il construira les autre rep tous seul) 
	//(Attention peut etre long si beaucoup de dossier) 
	m_pRootRep = new CRep(strRootPath, this, NULL); 
 
 
	if (m_pRootRep) 
		return true; 
	else	 
		return false; 
} 
 
//------------------------------------------------------------------------- 
void CRepExplorer::AddFileExtInFilter(CString strFileExt) 
{ 
	strFileExt.Remove('.'); 
	strFileExt.Remove('*'); 
	strFileExt.MakeUpper(); 
 
	m_FileExtFilterList.AddHead(strFileExt); 
} 
 
//------------------------------------------------------------------------- 
bool CRepExplorer::DelFileExtInFilter(CString strFileExt) 
{ 
	strFileExt.Remove('.'); 
	strFileExt.Remove('*'); 
	strFileExt.Remove(' '); 
	strFileExt.MakeUpper(); 
 
	POSITION pos = m_FileExtFilterList.GetHeadPosition(); 
	POSITION oldPos = NULL; 
 
	while (pos) 
	{ 
		CString strTmp = m_FileExtFilterList.GetNext(pos); 
 
		if (strTmp == strFileExt) 
		{ 
			m_FileExtFilterList.RemoveAt(oldPos); 
			return true; 
		} 
 
		oldPos = pos; 
	} 
 
	return false; 
} 
 
//------------------------------------------------------------------------- 
CList *  CRepExplorer::FindRepByName(CString strRepName) 
{ 
	m_RepFindList.RemoveAll(); 
	RecurRepFind(m_pRootRep, strRepName); 
 
	if (m_RepFindList.GetCount() > 0) 
		return &m_RepFindList; 
	else 
		return NULL; 
} 
 
//------------------------------------------------------------------------- 
CRep * CRepExplorer::RecurRepFind(CRep * pRep, CString strRepName) 
{ 
	CRep * pFindRep = NULL; 
	CRep * pNavRep = NULL; 
 
	if (pRep) 
	{ 
		POSITION pos = pRep->GetFirstRepPos(); 
 
		while (pos) 
		{ 
			pNavRep = pRep->GetNextRep(pos); 
 
			if (pNavRep->GetRepName() == strRepName) 
				m_RepFindList.AddTail(pNavRep); 
			else 
				if (pNavRep->bIsExistSubRep()) 
					pFindRep = RecurRepFind(pNavRep, strRepName); 
 
		} 
	} 
 
	return pFindRep; 
} 
 
//------------------------------------------------------------------------- 
CList * CRepExplorer::FindFileByName(CString strFileName) 
{ 
	m_RepFileFindList.RemoveAll(); 
	RecurRepFileFind(m_pRootRep, strFileName); 
 
	if (m_RepFileFindList.GetCount() > 0) 
		return &m_RepFileFindList; 
	else 
		return NULL; 
} 
 
//------------------------------------------------------------------------- 
void CRepExplorer::RecurRepFileFind(CRep * pRep, CString strFileName) 
{ 
	CRep * pFindRep = NULL; 
	CRep * pNavRep = NULL; 
 
	if (pRep) 
	{ 
		POSITION pos = pRep->GetFirstRepPos(); 
 
		while (pos) 
		{ 
			pNavRep = pRep->GetNextRep(pos); 
 
			if (pNavRep->bIsExistFile()) 
			{ 
				POSITION pos2 = NULL; 
 
				pNavRep->GetFirstFilePos(); 
 
				while(pos2) 
				{ 
					CRepFile * pFile = pNavRep->GetNextFile(pos2); 
					 
					if (pFile) 
					{ 
						if (pFile->GetFileName() == strFileName) 
							m_RepFileFindList.AddTail(pFile); 
					} 
				} 
 
			} 
			else 
				if (pNavRep->bIsExistSubRep()) 
					RecurRepFind(pNavRep, strFileName); 
 
		} 
	} 
} 
 
 
/************************************************************************** 
********************************  CRep  *********************************** 
***************************************************************************/ 
 
 
//------------------------------------------------------------------------- 
//Fonction récursive, qui est appeler un fois par CRepExplorer 
//avec le dossier de plus haut niveau, ensuite elle se charge de trouver et 
//créé tous ces dossiers fils  
//------------------------------------------------------------------------- 
CRep::CRep(CString strPath, CRepExplorer * pRepExplorer,CRep * pParent) 
{ 
	WIN32_FIND_DATA FindFileData; 
	char chTmpPath[255]; 
	 
	//Met a jour les variables 
	m_ListChildRep.RemoveAll(); 
	m_ListRepFile.RemoveAll(); 
	m_bExistFile = false; 
	m_bFileDetected = false; 
	m_pRepExplorer = pRepExplorer; 
	m_pParentRep = pParent; 
 
	//Ajoute *.* a la fin pour detecter tous les type de fichier 
	strPath += "\\*.*"; 
	HANDLE hFind = FindFirstFile(strPath, &FindFileData); 
	strPath.Delete(strPath.GetLength()-4,4); 
 
	int iPos = strPath.ReverseFind('\\'); 
	 
	m_strRepName = strPath; 
	m_strRepName.Delete(0,iPos+1); 
	m_strRepPath = strPath; 
   
	//Si rien n'a ete trouver on retourne 
	if (hFind==INVALID_HANDLE_VALUE) 
        return; 
 
	DWORD a = 0; 
    while (a != ERROR_NO_MORE_FILES) 
    { 
        if (!FindNextFile(hFind, &FindFileData)) 
            a = GetLastError(); 
        else 
        { 
            if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0) 
            { 
                strcpy(chTmpPath,strPath); 
                strcat(chTmpPath,"\\"); 
                strcat(chTmpPath,FindFileData.cFileName); 
             
				//ATTENTION il ne faut pas comparer directement , mais il faut dabort fire un & avec  
				//la cte FILE_ATTRIBUTE_DIRECTORY 
				if ((FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) 
				{ 
					//C'est un dossier donc on va le créé (fct recursive) 
                    CRep * pRep = new CRep(chTmpPath, m_pRepExplorer, this); 
 
					if (pRep) 
					{ 
						//Si il a été bien créé on l'ajoute a liste de dossier fils 
						m_ListChildRep.AddTail(pRep); 
					} 
				} 
                else 
                { 
					if (VerifExtInFilterList(CRepFile::ExtractExt(FindFileData.cFileName))) 
						m_bExistFile = true; 
 
					//Ne detecte les fichiers que si OnlyFolderDetect = false 
					//(C'est un option de constructTree) 
					if (!pRepExplorer->IsOnlyFolderDectect()) 
					{ 
						m_bFileDetected = true; 
						CRepFile * pRepFile = NULL; 
						pRepFile = CreateFilebyType(&FindFileData); 
						 
						//Le fichier a été créé 
						if (pRepFile) 
						{ 
							//Ajoute a la liste de fichier fils si sont extension 
							//est ds la liste de filtre (ou si on utilise pas de filtres) 
							if (VerifFileInFilterList(pRepFile)) 
								m_ListRepFile.AddTail(pRepFile); 
							else 
								delete pRepFile;// Sinon on le supprime 
						} 
					} 
                } 
            } 
        } 
    } 
 
    FindClose(hFind); 
} 
 
 
//------------------------------------------------------------------------- 
//C'est ici que vous devez rajouter vos instanciation de classe 
//si vous créé des classes pour gerer des nouveau type de fichier 
//------------------------------------------------------------------------- 
CRepFile * CRep::CreateFilebyType(WIN32_FIND_DATA * pFindFileData) 
{ 
	CRepFile * pRet = NULL; 
	CString strExtension; 
	strExtension = CRepFile::ExtractExt(pFindFileData->cFileName); 
 
	if (strExtension == "MP3") 
	{ 
		//fichier de type mp3 , je créé un object 
		//d'une classe speciale pour gerr le mp3 
		pRet = new CMp3File(pFindFileData, this); 
	} 
	else 
	{ 
		//Je créé un fichier standart 
		pRet = new CRepFile(pFindFileData, this); 
	} 
	 
	return pRet; 
} 
 
//------------------------------------------------------------------------- 
CRep::~CRep() 
{ 
	CRep * pNavRep = NULL; 
	POSITION pos = m_ListChildRep.GetHeadPosition(); 
 
	while (pos) 
	{ 
		pNavRep = m_ListChildRep.GetNext(pos); 
 
		if (pNavRep) 
			delete pNavRep; 
 
	} 
 
	CRepFile * pRepFile = NULL; 
	pos = m_ListRepFile.GetHeadPosition(); 
 
	while (pos) 
	{ 
		pRepFile = m_ListRepFile.GetNext(pos); 
 
		if (pRepFile) 
			delete pRepFile; 
 
	} 
} 
 
 
//------------------------------------------------------------------------- 
bool CRep::VerifFileInFilterList(CRepFile * pRepFile) 
{ 
	return VerifExtInFilterList(pRepFile->GetFileExt()); 
} 
 
//------------------------------------------------------------------------- 
bool CRep::VerifExtInFilterList(CString strExt) 
{ 
	if (m_pRepExplorer) 
	{ 
		if (m_pRepExplorer->bUseFilter()) 
		{ 
			CList * pList = m_pRepExplorer->GetFileExtFilterList(); 
 
			if (pList) 
			{ 
				POSITION pos = pList->GetHeadPosition(); 
 
				while (pos) 
				{ 
					CString strTmp = pList->GetNext(pos); 
 
					if (strTmp == strExt) 
						return true; 
				} 
			} 
		} 
		else 
			return true; 
	} 
		 
	return false; 
} 
 
//------------------------------------------------------------------------- 
CRep * CRep::GetRepByName(CString strRepName) const 
{ 
	CRep * pNavRep = NULL; 
	CRep * pRetRep = NULL; 
 
	POSITION pos = m_ListChildRep.GetHeadPosition(); 
 
	while (pos) 
	{ 
		pNavRep = m_ListChildRep.GetNext(pos); 
 
		if (pNavRep->m_strRepName == strRepName) 
		{ 
			pos = NULL; 
			pRetRep = pNavRep; 
		} 
 
	} 
 
	return pRetRep; 
} 
 
//------------------------------------------------------------------------- 
POSITION CRep::GetFirstRepPos() const 
{ 
	return m_ListChildRep.GetHeadPosition(); 
} 
 
//------------------------------------------------------------------------- 
CRep * CRep::GetNextRep(POSITION &pos) const 
{ 
	CRep * pNavRep = NULL; 
 
	if (pos && !m_ListChildRep.IsEmpty()) 
		pNavRep = m_ListChildRep.GetNext(pos); 
	else  
		pos = NULL; 
	 
	return pNavRep;	 
} 
 
//------------------------------------------------------------------------- 
POSITION CRep::GetFirstFilePos()  
{ 
	GetFolderFile(); 
	return m_ListRepFile.GetHeadPosition(); 
} 
 
//------------------------------------------------------------------------- 
CRepFile * CRep::GetNextFile(POSITION &pos) const 
{ 
	CRepFile * pNavFile = NULL; 
 
	if(pos && !m_ListRepFile.IsEmpty()) 
		pNavFile = m_ListRepFile.GetNext(pos); 
	else  
		pos = NULL; 
 
	return pNavFile;	 
} 
 
//------------------------------------------------------------------------- 
bool CRep::bIsExistFile()  
{ 
	if (!m_pRepExplorer->IsOnlyFolderDectect()) 
		return !m_ListRepFile.IsEmpty();  
	else 
		return m_bExistFile; 
} 
 
//------------------------------------------------------------------------- 
//Si les fichier n'ont pas été detecter pendant le construct tree 
//On le fait lors de l'appel a GetFirstFilePos() qui appele cette fct 
//qui s'occupe de detecter les fichier du dossier 
//------------------------------------------------------------------------- 
void CRep::GetFolderFile() 
{ 
	//Si on n'a pas fait la detection des fichier il 
	//faut la faire maintenant, si m_bFileDetected = true c'est que les fichiers 
	//on déja été detecter , on ne passe pas ds cette boucle 
	if (m_pRepExplorer->IsOnlyFolderDectect() && !m_bFileDetected) 
	{ 
		CString strPath = m_strRepPath + "\\*.*"; 
		WIN32_FIND_DATA FindFileData; 
		HANDLE hFind = FindFirstFile(strPath, &FindFileData); 
		if (hFind != INVALID_HANDLE_VALUE) 
		{ 
       		DWORD a = 0; 
			while (a != ERROR_NO_MORE_FILES) 
			{ 
				if (!FindNextFile(hFind, &FindFileData)) 
					a = GetLastError(); 
				else 
				{ 
					if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) 
					{ 
						if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0) 
						{ 
							CRepFile * pRepFile = NULL; 
							pRepFile = CreateFilebyType(&FindFileData); 
 
							if (pRepFile) 
							{ 
								if (VerifFileInFilterList(pRepFile)) 
									m_ListRepFile.AddTail(pRepFile); 
								else 
									delete pRepFile; 
							} 
						} 
					} 
				} 
 
				m_bFileDetected = true; 
			} 
		} 
	} 
} 
 
 
//------------------------------------------------------------------------- 
CRep * CRep::AddSubRep(CString strRepName) 
{ 
	CString strPath = m_strRepPath + "\\" + strRepName; 
 
	CRep * pRep = NULL; 
	LPSECURITY_ATTRIBUTES lpSecure = new SECURITY_ATTRIBUTES; 
 
	lpSecure->nLength = sizeof(SECURITY_ATTRIBUTES); 
	lpSecure->lpSecurityDescriptor = NULL; 
 
	if(CreateDirectory(strPath, lpSecure) != 0) 
	{ 
		pRep = new CRep(strPath,m_pRepExplorer,this); 
 
		if (pRep) 
			m_ListChildRep.AddTail(pRep); 
	} 
	 
	if (lpSecure)  
		delete lpSecure; 
 
	return pRep; 
} 
 
 
//-------------------------------------------------------------------------	 
bool CRep::ModifRepName(CString strRepNewName) 
{ 
	CString strSrcPath = m_strRepPath; 
	CString strDestPath = m_strRepPath; 
	 
	int iPos = strDestPath.ReverseFind('\\'); 
	strDestPath.Delete(iPos, strDestPath.GetLength()-iPos); 
	strDestPath += "\\" + strRepNewName;	 
		 
	if (MoveFile(strSrcPath,strDestPath) != 0) 
	{ 
		m_strRepName = strRepNewName; 
		m_strRepPath = strDestPath; 
		return true; 
	} 
	return false; 
} 
 
//-------------------------------------------------------------------------	 
bool CRep::bIsExistSubFile() 
{ 
	POSITION pos = m_ListChildRep.GetHeadPosition(); 
 
	while (pos) 
	{ 
		CRep * pRep = m_ListChildRep.GetNext(pos); 
 
		if (pRep) 
		{ 
			if (pRep->bIsExistFile()) 
				return true; 
			else 
				if (pRep->bIsExistSubFile() == true) 
					return true; 
		} 
	} 
 
	return false; 
} 
 
 
//------------------------------------------------------------------------- 
bool CRep::DeleteSubRep(CString strRepName) 
{ 
	bool bRet = false; 
 
	CRep * pRepToDel = GetRepByName(strRepName); 
	if (pRepToDel) 
	{ 
		bRet = DeleteRoutine(pRepToDel->m_strRepPath); 
		if (pRepToDel) 
		{ 
			if (DeleteInChildList(pRepToDel)) 
				delete pRepToDel; 
		} 
	} 
	 
	return bRet; 
} 
 
//------------------------------------------------------------------------- 
bool CRep::DeleteThisRep() 
{ 
	bool bRet = false; 
	bRet = DeleteRoutine(m_strRepPath); 
	if (bRet) 
	{ 
		CRep * pParent = GetParentRep(); 
 
		//On se supprime de la liste du pere 
		if (pParent) 
			if (pParent->DeleteInChildList(this)) 
				delete this;//on se supprime 
	} 
 
	return bRet; 
} 
 
 
//------------------------------------------------------------------------- 
bool CRep::DeleteInChildList(CRep * pRep) 
{ 
	if (pRep) 
	{ 
		POSITION pos = m_ListChildRep.GetHeadPosition(); 
		POSITION oldPos = pos;//Sinon si c'est le premier sa explose 
 
		while (pos) 
		{ 
			CRep * pRepToDel = m_ListChildRep.GetNext(pos); 
 
			if (pRepToDel == pRep) 
			{ 
				//On delete oldpos car sinon on va supprimer le prochain 
				m_ListChildRep.RemoveAt(oldPos); 
				return true; 
			} 
 
			oldPos = pos; 
		} 
 
		if (m_ListChildRep.IsEmpty()) 
			m_bExistFile = false; 
	} 
 
	return false; 
 
} 
 
 
//------------------------------------------------------------------------- 
bool CRep::DeleteRoutine(CString strRepPath) 
{ 
	//Detruit recursivement tous les fichier est dossier 
	int s = strlen(strRepPath); 
     
	TCHAR * rep = new TCHAR[strlen(strRepPath)+2]; 
    strcpy(rep, strRepPath); 
    rep[strlen(strRepPath)+1] = '\0'; 
    SHFILEOPSTRUCT sh; 
    sh.hwnd = NULL; 
    sh.wFunc = FO_DELETE; 
    sh.pFrom = rep; 
    sh.pTo = NULL; 
    sh.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; 
    sh.fFlags |= FOF_ALLOWUNDO; 
    sh.fAnyOperationsAborted = FALSE; 
    sh.lpszProgressTitle = NULL; 
    sh.hNameMappings = NULL; 
     
    bool iRet = (SHFileOperation(&sh)==0); 
	delete [] rep; 
	return iRet; 
} 
 
 
/************************************************************************** 
*******************************  CRepFile  ******************************** 
***************************************************************************/ 
 
//------------------------------------------------------------------------- 
CRepFile::CRepFile(WIN32_FIND_DATA * pFindFileData, CRep * pFileRep) 
{ 
	if (pFindFileData) 
	{ 
		m_iFileSize = (pFindFileData->nFileSizeHigh * ((long)MAXDWORD+1) + pFindFileData->nFileSizeLow); 
		m_strFileName = pFindFileData->cFileName; 
		m_ftCreationTime = pFindFileData->ftCreationTime; 
		m_ftLastAccessTime = pFindFileData->ftLastAccessTime; 
		m_ftLastWriteTime = pFindFileData->ftLastWriteTime; 
		m_pFileRep = pFileRep; 
 
		m_strFileExt = ExtractExt(m_strFileName); 
	} 
} 
 
//------------------------------------------------------------------------- 
CRepFile::~CRepFile() 
{ 
 
} 
 
//------------------------------------------------------------------------- 
void CRepFile::GetTimeAttribute(FILETIME * pftCreationTime, FILETIME * pftLastAccessTime, 
								FILETIME * pftLastWriteTime) 
{ 
	pftCreationTime   = &m_ftCreationTime; 
	pftLastWriteTime  = &m_ftLastWriteTime; 
	pftLastAccessTime = &m_ftLastAccessTime; 
} 
 
//------------------------------------------------------------------------- 
CString CRepFile::ExtractExt(CString strFileName) 
{ 
	CString strFileExt = strFileName; 
 
	int iPos = strFileExt.ReverseFind('.'); 
	strFileExt.Delete(0,iPos+1); 
	strFileExt.Remove('.'); 
	strFileExt.MakeUpper(); 
 
	return strFileExt; 
} 
 
/************************************************************************** 
*******************************  CAudioFile  ******************************** 
***************************************************************************/ 
CAudioFile::CAudioFile(WIN32_FIND_DATA * pFindFileData, CRep * pFileRep) : CRepFile(pFindFileData,pFileRep) 
{ 
 
} 
 
 
//--------------------------------------------------------------------------- 
CTimeSpan CAudioFile::GetFileLenght() 
{ 
	return m_FileLenght ; 
} 
 
//--------------------------------------------------------------------------- 
CString CAudioFile::GetStringLenght() 
{ 
	CString strTmp; 
	strTmp.Format("%d min : %d s",m_FileLenght.GetMinutes(), m_FileLenght.GetSeconds()); 
	return strTmp; 
} 
 
/************************************************************************** 
*******************************  CMp3File  ******************************** 
***************************************************************************/ 
CMp3File::CMp3File(WIN32_FIND_DATA * pFindFileData, CRep * pFileRep) : CAudioFile(pFindFileData,pFileRep) 
{ 
	HANDLE hFile; 
	LPSTR lpRead; 
	DWORD nLus; 
	CString strFilePath; 
 
	char szTitle[30]; 
	char szArtist[30]; 
	char szAlbum[30]; 
	char szYear[4]; 
	char szComment[30]; 
 
	szTitle[0] = '\0'; 
	szArtist[0] = '\0'; 
	szAlbum[0] = '\0'; 
	szYear[0] = '\0'; 
	szComment[0] = '\0'; 
 
 
	// si le nom du fichier n'est pas spécifié 
	if(pFindFileData->cFileName[0] == '\0') 
	{ 
		return; 
	} 
	else 
	{ 
		strFilePath = pFileRep->GetRepPath(); 
		strFilePath += "\\"; 
		strFilePath += m_strFileName; 
	} 
 
	hFile = CreateFile(strFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 
 
	// si erreur pendant CreateFile 
	if(hFile == INVALID_HANDLE_VALUE) 
	{ 
		return; 
	} 
 
	// si la taille du mp3 ne permet pas la place du tag 
	if(m_iFileSize < 129) 
	{ 
		CloseHandle(hFile); 
		return; 
	} 
 
	// on se déplace ds le fichier 
	SetFilePointer(hFile, - 128, 0, FILE_END); 
 
	// allocation mémoire pr le buffer de lecture 
	lpRead = (LPSTR) GlobalAlloc(GPTR, 128); 
 
	// lecture du tag 
	ReadFile(hFile, lpRead, 128, &nLus, NULL); 
 
	// si la chaine de commence pas par 'TAG' 
	if(lpRead[0] != 'T' || lpRead[1] != 'A' || lpRead[2] != 'G') 
	{ 
		CloseHandle(hFile); 
		return; 
	} 
 
	// extraction des informations 
	Copy(3, 30, lpRead, szTitle); 
	Copy(33, 30, lpRead, szArtist); 
	Copy(63, 30, lpRead, szAlbum); 
	Copy(93, 4, lpRead, szYear); 
	Copy(97, 30, lpRead, szComment); 
	m_nGenre = lpRead[127]; 
 
	m_strTitle = szTitle; 
	m_strArtist = szArtist; 
	m_strAlbum = szAlbum; 
	m_strYear = szYear; 
	m_strComment = szComment; 
 
	CloseHandle(hFile); 
	GlobalFree(lpRead); 
 
	m_FileLenght = ReadLenght(strFilePath); 
} 
 
//------------------------------------------------------------- 
CTimeSpan CMp3File::ReadLenght(CString strFilePath) 
{ 
	//On suppose qu'on est en Version 1, layer 3 
 
	long size; 
	unsigned char c; 
	FILE* file; 
	int b,s; 
 
	/* ouvre le mp3 */ 
	file=fopen(strFilePath,"rb"); 
 
	/* boucle pour trouver le bitrate */ 
	do 
	{ 
		do 
		{ 
		/* cherche un octet dont tous */ 
		/* les bits sont positifs */ 
			do 
			{ 
			c=fgetc(file); 
			} while (c!=0xFF); 
 
			/* lit un second octet */ 
			c=fgetc(file); 
 
		/* sort de la boucle si les 4 premiers bits sont positifs */ 
		} while ((c&0xF0)!=0xF0); 
 
			/* lit les 4 premiers bits de l'octet suivant */ 
			c=(fgetc(file)&0xF0)>>4; 
 
			/* regarde a quel bitrate les 4 bits correspondent */ 
			 
			switch (c) 
			{ 
				case 0x01: b = 32 ;break; 
				case 0x02: b = 40 ;break; 
				case 0x03: b = 48 ;break; 
				case 0x04: b = 56 ;break; 
				case 0x05: b = 64 ;break; 
				case 0x06: b = 80 ;break; 
				case 0x07: b = 96 ;break; 
				case 0x08: b = 112 ;break; 
				case 0x09: b = 128 ;break; 
				case 0x10: b = 160 ;break; 
				case 0xA:  b = 192 ;break; 
				case 0xB:  b = 224 ;break; 
				case 0xC:  b = 256 ;break; 
				case 0xD:  b = 320 ;break; 
				default :  b = 1   ;break; 
			} 
 
 
	/* recommence si on a un bitrate erronee */ 
	} while ((b==0)||(b==999)); 
 
	/* va a la fin du mp3 */ 
	fseek(file,0,SEEK_END); 
 
	/* recupere la position (donc la taille du mp3) */ 
	size=ftell(file); 
 
	/* ferme le mp3 */ 
	fclose(file); 
 
	/* calcule la duree d'apres le bitrate et la taille du fichier */ 
	s=(size/((b)<<7)); 
 
	/* attention la duree obtenue est aproximative ! */ 
	int iTimeMin = abs(s/60); 
	float iTmp = ((float)s/60) - iTimeMin; 
	int iTimeSec = (int)(iTmp * 60); 
 
 
	return CTimeSpan(0,0,iTimeMin,iTimeSec+5); 
} 
 
 
//------------------------------------------------------------- 
CMp3File::~CMp3File() 
{ 
 
} 
 
//------------------------------------------------------------- 
void CMp3File::Copy(DWORD nBegin, DWORD nLength, LPSTR lpSrc, char szDest[]) 
{ 
  char *dest, *src; 
  DWORD i; 
 
  src = lpSrc; 
  dest = szDest; 
 
  src += nBegin; 
 
  for(i = 0; i < nLength; i++) 
    *dest++ = *src++; 
}