#include "stdafx.h"
#include "NcFolder.h"
#include "include\fs.h"
#include "ncmedia.h"
#include "img2gba\convert.h"
#include "2mp3\sox.h"
#include "FileCopyProgress.h"

//#include <process.h>
#define BOOK_DATA 1
#define MUSIC_DATA 2
#define PIC_DATA 3
#define MAX_FILENAME 15
#define BOOKMARKLEN 32 
///////////////////
//判断mp3类型数否支持

/*
Bitrate index
bits V1,L1 V1,L2 V1,L3 V2,L1 V2,L2 V2,L3 
0000 free free free free free free 
0001 32 32 32 32 32 8 (8) 
0010 64 48 40 64 48 16 (16) 
0011 96 56 48 96 56 24 (24) 
0100 128 64 56 128 64 32 (32) 
0101 160 80 64 160 80 64 (40) 
0110 192 96 80 192 96 80 (48) 
0111 224 112 96 224 112 56 (56) 
1000 256 128 112 256 128 64 (64) 
1001 288 160 128 288 160 128 (80) 
1010 320 192 160 320 192 160 (96) 
1011 352 224 192 352 224 112 (112) 
1100 384 256 224 384 256 128 (128) 
1101 416 320 256 416 320 256 (144) 
1110 448 384 320 448 384 320 (160) 
1111 bad bad bad bad bad bad 
 
NOTES: All values are in kbps
V1 - MPEG Version 1
V2 - MPEG Version 2 and Version 2.5
L1 - Layer I
L2 - Layer II
L3 - Layer III
"free" means variable bitrate.
"bad" means that this is not an allowed value 
*/
const int  BitrateArray[16][6]=
{
{0,0,0,0,0,0},
{32, 32, 32, 32, 32, 8},
{64, 48, 40, 64, 48, 16},
{96, 56, 48, 96, 56, 24},
{128, 64, 56, 128, 64, 32 },
{160, 80, 64, 160, 80, 64},
{192, 96 ,80, 192 ,96, 80 },
{224 ,112, 96 ,224, 112, 56},
{256, 128, 112, 256 ,128, 64},
{288 ,160 ,128 ,288, 160 ,128},
{320 ,192,160, 320, 192, 160},
{352 ,224, 192, 352, 224 ,112},
{384, 256, 224, 384, 256, 128},
{416 ,320 ,256, 416, 320 ,256},
{448, 384, 320,448, 384,320},
{-1,-1,-1,-1,-1,-1}
};
 
/*
Sampling rate frequency index (values are in Hz) bits MPEG1 MPEG2 MPEG2.5 
00 44100 22050 11025 
01 48000 24000 12000 
10 32000 16000 8000 
11 reserv. reserv. reserv. 
*/
const int SamplingRateArray[4][3]=
{
{44100, 22050 ,11025},
{48000 ,24000 ,12000},
{32000, 16000 ,8000},
{1,1,1}
};
 
/*
Padding bit
0 - frame is not padded
1 - frame is padded with one extra bit
*/
 
#define MP3VERSIONMASK   0x18
#define MP3LAYERMASK     0x06
#define MP3BitRateMask    0xF0
#define MP3SamplingMask   0x0C
#define MP3PadingMask     0x02
/*
判断一个mp3文件是否属于v1 layer3 类型。
*/
#define BUFSIZE 1024
bool _IsMPEGV1L3File(LPCTSTR pMp3FilePath,int * pMp3StartOffset)
{
	CFile mp3Fd;
	if(mp3Fd.Open(pMp3FilePath,CFile::modeReadWrite)==false)
		return false;
	unsigned char buf[BUFSIZE];
	unsigned char checkBuf[2];
	DWORD dwRead,dwReadCount;
	int    filesize=mp3Fd.GetLength();//	.GetSize();
	int i=0,seekoffset=0;
	*pMp3StartOffset=0;
	while( dwRead=mp3Fd.Read(buf, BUFSIZE),dwRead>0 ) 
	{
		for( i=0;i<dwRead;i++)
		{
			if((buf[i]==0xFF)&&(buf[i+1]==0xFB))
			{
				int FrameSize,BitRateValue , SamplingValue,PaddingValue;
				int BitRateValueIndex , SamplingValueIndex;
				
				BitRateValueIndex = buf[i+2] & MP3BitRateMask;
				BitRateValueIndex >>= 4 ;
				BitRateValue=BitrateArray[BitRateValueIndex][2];
				if(BitRateValue==0||BitRateValue==-1)
					continue;
				SamplingValueIndex=buf[i+2] & MP3SamplingMask;
				SamplingValueIndex >>= 2;
				if(SamplingValueIndex==3)
					continue;
				SamplingValue=SamplingRateArray[SamplingValueIndex][0];
				
				PaddingValue=buf[i+2] & MP3PadingMask;
				PaddingValue >>= 1;
				
				FrameSize=144*BitRateValue*1000/SamplingValue+PaddingValue;
				if(FrameSize<=0){
					continue;
				}
				else
				{
					//从文件中读出seekoffset+i+FrameSize位置的值，看是否是0xFFFB
					if((i+FrameSize+1)<BUFSIZE)
					{
						if((buf[i+FrameSize]==0xFF)&&(buf[i+FrameSize+1]==0xFB))
						{
							mp3Fd.Close();
							*pMp3StartOffset=seekoffset+i;
							return true;
						}
					}
					else    
					{
						if(filesize<seekoffset+i+FrameSize+1)
							continue;
						int currentoffset=mp3Fd.GetPosition();
						mp3Fd.Seek(seekoffset+i+FrameSize,FILE_BEGIN);
						dwReadCount=mp3Fd.Read(checkBuf,2);
						if(dwReadCount!=2)
						{
							mp3Fd.Close();
							return false;
						}
						else 
						{
							if((checkBuf[0]==0xFF)&&(checkBuf[1]==0xFB))
							{
								mp3Fd.Close();
								*pMp3StartOffset=seekoffset+i;
								return true;
							}
						}
						mp3Fd.Seek(currentoffset,FILE_BEGIN);
					}
				}
			}
		}
		seekoffset+=i;
	}
	mp3Fd.Close();
	return false;
	
}
//////////////////
CNcFolder::CNcFolder(void)
{
}

CNcFolder::~CNcFolder(void)
{
	//if(mediaFsOpened())
	//	mediaFsClose();
}
HRESULT CNcFolder::OpenDevice()
{
	//DWORD nPartition = 0;
	if(!mediaFsOpened())
	{
		if(mediaFsOpen("127.0.0.1", 20081)<0)
		{
			MessageBox(NULL,"连接iQue聚乐卡失败，请检查设备连接是否正常,或者请重启游戏机。","错误",MB_OK);
			return E_FAIL;
		}
		char devCurVol[32];
		strcpy(devCurVol,"book");
		int numEntries;
		if(ISFS_ReadDir((const u8*)devCurVol,NULL,(u32*)&numEntries)!=ISFS_ERROR_OK)
		{
			TRACE("open device failed");
			MessageBox(NULL,"连接iQue聚乐卡失败，请检查设备连接是否正常,或者请重启游戏机。","错误",MB_OK);
			return E_FAIL;
		}
		/*
		ISFSStats status;
				if(ISFS_GetStats(&status) <0) 
				{
					return E_FAIL;
				}*/
				
	}
	return S_OK;
}
void GetWorkPath(TCHAR pPath[MAX_PATH])
{
	HKEY hkey; 
	char sz[MAX_PATH]; 
	DWORD dwtype, sl = 256; 
	RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
		"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\iQue NetCard VNProxy", 
		NULL, KEY_ALL_ACCESS, &hkey); 
	RegQueryValueEx(hkey, "Uninstallstring", NULL, &dwtype, (LPBYTE)sz, &sl); 
	RegCloseKey(hkey); 
	_tcscpy(pPath,sz);
}
HRESULT CNcFolder::CloseDevice()
{
	//DWORD nPartition = 0;
	if(mediaFsOpened())
	{
		mediaFsClose();
	//return E_FAIL;
	}
	return S_OK;
}
void GetLastDotPos(LPCTSTR pFileName,LPTSTR pSufix)
{
	LPCTSTR p=NULL,pTemp=NULL;
	LPTSTR p2;
	pTemp=pFileName;
	while((p=_tcschr(pTemp,_T('.')))!=NULL)
	{
		pTemp=::CharNext(p);
	}
	_tcscpy(pSufix,pTemp);
	//change all the letters into lowercase
	p2=pSufix;
	while(*p2!=0)
	{
		if((*p2<=90)&&(*p2>=65))
			(*p2)+=32;

		p2=::CharNext(p2);
	}
}
BOOL _FindUniqueRealFileName(LPCTSTR vol, LPTSTR pstrName) 
{
	ATLASSERT(!::IsBadWritePtr(pstrName, MAXNAMELEN));
	//  ATLASSERT(vol.IsOpen());

	USES_CONVERSION;
	const int MAX_TRIES = 200;

	TCHAR szNewName[MAXNAMELEN+1];
	bool bFoundUnique = false;
	bool bFoundName=false;

	TCHAR pSufix[10];
	memset(pSufix,0,sizeof(TCHAR)*10);
	GetLastDotPos(pstrName, pSufix);
	for( int i=1; !bFoundUnique && (i<MAX_TRIES); i++ ) 
	{
		bFoundName = false;
		::wsprintf(szNewName, _T("%d.%s"), i,pSufix); 
		//遍历目录下所有文件,比较文件名,看是否有重名.
		// Scan folder
		ISFSError err;
		int num,j;
		err=ISFS_ReadDir((const u8*)vol,NULL, (u32*)&num);
		if(err<0)
		{
			ATLTRACE(_T("Error: _CountFilesInFolder() read directory info failed!\r\n"));
			return E_FAIL;
		}
		if(num>0)
		{
			TCHAR szBuf[MAX_TOTAL_SIZE];
			TCHAR * pData;
			memset(szBuf,0,sizeof(TCHAR)*MAX_TOTAL_SIZE);
			err=ISFS_ReadDir((const u8*)vol,(u8*)szBuf,(u32*) &num);
			if(err<0)
			{
				ATLTRACE(_T("Error: _CountFilesInFolder() read directory info failed!\r\n"));
				return E_FAIL;
			}
			pData=szBuf;
			for(j=0;j<num;j++)
			{
				TCHAR szFileName[MAXNAMELEN];
				memset(szFileName,0,sizeof(TCHAR)*MAXNAMELEN);
				_tcscpy(szFileName,pData);
				if( _tcscmp(szFileName, _T("."))==0 ) continue;
				if( _tcscmp(szFileName, _T(".."))==0 ) continue;
				if( _tcsicmp(A2CT(szFileName), szNewName)==0 ) {
					bFoundName = true;
					break;
				}     
				while(*pData!=0)
				{
					pData=::CharNext(pData);
				}
				*pData=_T('e');  //replace the EOF with 'e' , so the next CharNext() calling will work.
				pData=::CharNext(pData);
			}
		}

		bFoundUnique = !bFoundName;
	}
	if( !bFoundUnique ) return FALSE;
	_tcscpy( pstrName, szNewName );
	return TRUE;
}
void _WriteBookDFN(IOSFd fd,LPCTSTR pDisplayName)
{
	ISFSError err;
	u8 buf[2];
	USES_CONVERSION;
	memset(buf,0,2);
	//_tcscpy((char*)_T(buf),(const char*)A2CW(pDisplayName));
	err=ISFS_Seek(fd, 0, SEEK_SET);
	err=ISFS_Write(fd,(const u8*)T2CW(pDisplayName),30);
	err=ISFS_Write(fd,buf,2);
}
/*
void _WriteMp3DFN(IOSFd fd,LPCTSTR pDisplayName,int type)
{
	ISFSError err;
	TCHAR szTempTitle[MAXNAMELEN+1];
	
	USES_CONVERSION;
	err=ISFS_Seek(fd,TAGPOS,SEEK_END);
	err=ISFS_Read(fd,(u8*)szTempTitle,3);
	if(err<0)
   	{
		if(mediaFsOpened())
			mediaFsClose();
   	}
	szTempTitle[3]=_T('\0');
	if(_tcscmp(szTempTitle,"TAG")!=0)
   	{
		//ID3v1标签不存在.要在文件末尾写入完整的标签。
		char  ID3v1Tag[ID3V1TAGSIZE];
		memset(ID3v1Tag,0,ID3V1TAGSIZE);
		strcpy(ID3v1Tag,"TAG");
		ID3v1Tag[ID3V1TAGSIZE-1]=0xFF;
		err=ISFS_Seek(fd,0,SEEK_END);
		err=ISFS_Write(fd,(const u8*)ID3v1Tag,ID3V1TAGSIZE);
   	}
	
	//ID3v1标签已经存在.只需要修改对应title项内容。
	err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
	memset(szTempTitle,0,sizeof(TCHAR)*31);
	if(type==COPY_TYPE)
   	{
		//如果原名已经存在
		err=ISFS_Read(fd, (u8 *)szTempTitle, 30);
		//对读取的title 作一次清理，把末尾的空格去掉。
		if(szTempTitle[0]==_T('\0'))
		{
			err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
			char buf[100];
			_tcsncpy(buf,pDisplayName,30);
			err=ISFS_Write(fd, (const u8*)T2CW(pDisplayName),30);
		}
		else
		{
			err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
			err=ISFS_Write(fd, (const u8*)T2CW(szTempTitle), 30);
		}
   	}
	else if (type==RENAME_TYPE)
   	{
		err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
		char buf[100];
		_tcsncpy(buf,pDisplayName,30);
		err=ISFS_Write(fd, (const u8*)T2CW(pDisplayName),30);
		
   	}
	
}*/



void _WriteMp3DFN(IOSFd fd,LPCTSTR pDisplayName,int type)
{
	ISFSError err;
	TCHAR szTempTitle[MAXNAMELEN+1];
	
	USES_CONVERSION;
	err=ISFS_Seek(fd,TAGPOS,SEEK_END);
	err=ISFS_Read(fd,(u8*)szTempTitle,3);
	if(err<0)
   	{
		if(mediaFsOpened())
			mediaFsClose();
   	}
	szTempTitle[3]=_T('\0');
	if(_tcscmp(szTempTitle,"TAG")!=0)
	{
		//ID3v1标签不存在.要在文件末尾写入完整的标签。
		char  ID3v1Tag[ID3V1TAGSIZE];
		memset(ID3v1Tag,0,ID3V1TAGSIZE);
		strcpy(ID3v1Tag,"TAG");
		ID3v1Tag[ID3V1TAGSIZE-1]=0xFF;
		err=ISFS_Seek(fd,0,SEEK_END);
		err=ISFS_Write(fd,(const u8*)ID3v1Tag,ID3V1TAGSIZE);
	}

	//ID3v1标签已经存在.只需要修改对应title项内容。
	err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
	memset(szTempTitle,0,sizeof(TCHAR)*31);
	if(type==COPY_TYPE)
	{
		//如果原名已经存在
		err=ISFS_Read(fd, (u8 *)szTempTitle, 30);
		//对读取的title 作一次清理，把末尾的空格去掉。
		if(szTempTitle[0]==_T('\0'))
		{
			err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
			char buf[100];
			_tcsncpy(buf,pDisplayName,30);
			err=ISFS_Write(fd, (const u8*)T2CW(pDisplayName),30);
		}
		else
		{
			err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
			//strcat(szTempTitle,".mp3");
			err=ISFS_Write(fd, (const u8*)T2CW(szTempTitle), 30);
		}
	}
	else if (type==RENAME_TYPE)
	{
		err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);	
		char buf[100];
		_tcsncpy(buf,pDisplayName,30);
		err=ISFS_Write(fd, (const u8*)T2CW(pDisplayName),30);
	/*	_tcscpy( szTempTitle,(const char*)T2CW(pDisplayName));
		err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
		err=ISFS_Write(fd, (const u8*)szTempTitle, 30);*/
	}

}

void _SetFileWritePos(CFile *srcFd,IOSFd fd,LPTSTR pRealName)
{
	ISFSError err;
	TCHAR pSufix[32];
	memset(pSufix,0,sizeof(TCHAR)*32);
	GetLastDotPos(pRealName,pSufix); 
	if(_tcscmp(pSufix,_T("mp3"))==0)//
	{
		//如果是mp3文件，我们需要清除开始处的id3 信息。
		#define TEMPBUFSIZE 1024
		unsigned char buf[TEMPBUFSIZE];
		DWORD dwRead;
		//CFileStatus fstat;
		//fstat=srcFd->SeekToEnd();
		err=ISFS_Write(fd,(u8*)pSufix,DISPLAYNAMELEN+BOOKMARKLEN);//change
		int filesize=srcFd->SeekToEnd();//	.GetSize();
		srcFd->SeekToBegin();
		int i=0,seekoffset=0;
		while( dwRead=srcFd->Read(buf, TEMPBUFSIZE), dwRead>0 ) 
		{
			for( i=0;i<dwRead;i++)
			{
				if(buf[i]==0xFF && buf[i+1]==0xFB)
				{
					break;
				}
			}
			seekoffset+=i;
			if(i!=dwRead)
			{
				srcFd->Seek(seekoffset,FILE_BEGIN);
				break;
			}
		}
	}
	else 
	{
		err=ISFS_Write(fd,(u8*)pSufix,DISPLAYNAMELEN+BOOKMARKLEN);
		//err=ISFS_Write(fd,(u8*)pSufix,DISPLAYNAMELEN);
	}
}
void  _WriteDisplayFileName(IOSFd fd,LPCTSTR pRealName,LPCTSTR pDisplayName,int type)
{
	TCHAR pSufix[10];
	memset(pSufix,0,sizeof(TCHAR)*10);
	GetLastDotPos(pRealName,pSufix); 
	
	//if(_tcscmp(pSufix,_T("mp3"))==0)
	//	_WriteMp3DFN(fd,pDisplayName,type);
	//else 
		_WriteBookDFN(fd,pDisplayName);
}
#define MINIBUFSIZE (512*1024)
#define MAXBUFSIZE (2*1024*1024)
#define MUSICMAXSIZE (1024*1024*12)
HRESULT CopyData(IOSFd ncf,CFile *pcf,int filesize)
{
	BYTE* buf=NULL;
	int bufsize;
	ISFSError err;
	DWORD dwRead;
	int finishedsize=0;
	
	if(filesize<=MINIBUFSIZE)
		bufsize=filesize;
	else if( filesize<=MUSICMAXSIZE)
		bufsize=MINIBUFSIZE;
	else 
		bufsize=MAXBUFSIZE;
	
	buf=(BYTE*)malloc(bufsize);
	if(buf==NULL)
	{
		return E_FAIL;
	}
//	FILE dp;
	
	//open()
	while( dwRead=pcf->Read(buf, bufsize),dwRead >0 ) 
	{
		err=ISFS_Write(ncf,buf, dwRead);
		if( err<0 )
		{
			ATLTRACE(_T("Error:_CopyFile() write file fail! err=%d \r\n"),err);
			break ;
		}
		finishedsize+=dwRead;	
	}
	ISFS_Close(ncf);
	free(buf);
	return S_OK;
}
HRESULT CopyDataFromNC(CFile *pcf,IOSFd ncf)
{
	BYTE* buf=NULL;
	int bufsize;
	int restdata=0;
	ISFSError err;
//	DWORD dwRead;
	int finishedsize=0;
	ISFSFileStats stats;
	
	if(ISFS_GetFileStats(ncf, &stats)<0)
	{
		ATLTRACE(_T("Error: read() read file state failed!\r\n"));
		return S_FALSE;
	}
	if( stats.size==0 ) return S_FALSE;
	restdata=stats.size;

	if(restdata<=MINIBUFSIZE)
		bufsize=restdata;
	else if( restdata<=MUSICMAXSIZE)
		bufsize=MINIBUFSIZE;
	else 
		bufsize=MAXBUFSIZE;

	buf=(BYTE*)malloc(bufsize);
	if(buf==NULL)
	{
		return E_FAIL;
	}
	//	FILE dp;

	//open()
//	while( dwRead=pcf->Read(buf, bufsize),dwRead >0 ) 
	ISFS_Seek(ncf,65,0);
	while( ISFS_Read(ncf,(u8*)buf,bufsize),restdata >0 ) 
	{
		//err=ISFS_Write(ncf,buf, dwRead);
		 pcf->Write(buf,bufsize);
		
		if(restdata > bufsize)
			restdata=restdata-bufsize;
		else
		{
			bufsize=restdata;
			restdata=-1;
		}
		
	}
	free(buf);
	return S_OK;
}
HRESULT CNcFolder::GetNCFile(LPCTSTR pstrFileName,int datatype)
{
	HRESULT hr;
	TCHAR realname[MAX_PATH];
	TCHAR WindowTemp[]=_T("\\temp\\");
	TCHAR szWindowsPath[MAX_PATH];
	IOSFd ncf;
//	ISFSError err;

	::GetWindowsDirectory(szWindowsPath,MAX_PATH);
	_tcscat(szWindowsPath,WindowTemp);
	_tcscat(szWindowsPath,pstrFileName);
	CFile pcf;
	if( pcf.Open(szWindowsPath,CFile::modeCreate|CFile::modeWrite )==FALSE ) 
	{
		if(mediaFsOpened())
			mediaFsClose();
		return E_FAIL;
	}
//	ISFSFileStats status;
	hr=disp2real(pstrFileName,realname,datatype);
	if( (ncf=ISFS_Open((const u8*)realname, ISFS_READ_ACCESS))<0) 
	{
		if(mediaFsOpened())
			mediaFsClose();
		pcf.Close();
		return E_ACCESSDENIED;
	}
	ISFSFileStats stats;
	int restdata=0;
	if(ISFS_GetFileStats(ncf, &stats)<0)
	{
		ATLTRACE(_T("Error: read() read file state failed!\r\n"));
		return E_FAIL;
	}
		if( stats.size==0 ) return E_FAIL;
	//hr=CopyDataFromNC(&pcf,ncf);
		CFileCopyProgress dlg;
		dlg.pPcFd=&pcf;
		dlg.ncFd=ncf;
		dlg.NCFlag=2;//pc2nc
		dlg.fsize=stats.size;
	
	//dlg.m_pstrFileName=szDestName; //
	UINT res=dlg.DoModal();
	if(res==IDCANCEL)
   	{		
   	    ISFS_Close(ncf);//added 
		DelFile(szWindowsPath,0);
   	}

	return S_OK;

}
HRESULT CNcFolder::GetDisplayNameOf(IOSFd fd, ncfileinfo *finfo,int datatype)
{
	USES_CONVERSION;

	ISFSError err;
//	LPCTSTR pstrFileName ;
	wchar_t szTempTitle[MAX_PATH];

	//	::wsprintf(pstrFileName,_T("%s"),pstrealName);
	switch(datatype)
	{
	case 9 :
		err=ISFS_Seek(fd, MP3DISPLAYNAMEPOS, SEEK_END);
		//memset(szTempTitle,0,sizeof(TCHAR)*31);
		err=ISFS_Read(fd, (u8 *)szTempTitle, 30);
		_tcscpy(finfo->filename,W2CT(szTempTitle));
		finfo->filesize=ISFS_GetSize(fd);
		break;
	default:
		err=ISFS_Seek(fd, 0, SEEK_SET);
		err=ISFS_Read(fd, (u8 *)szTempTitle, 30);
		//memset(finfo->filename,0,sizeof(TCHAR)*(MAXNAMELEN+1));
		_tcscpy(finfo->filename,W2CT(szTempTitle));
		// wsprintf(finfo->filename ,_T("%s"),W2CT(szTempTitle));
		finfo->filesize=ISFS_GetSize(fd);
		//_tcscpy( finfo->filename,szTempTitle);
		//finfo->filesize=ISFS_GetSize(fd);
		break;
	}


	return S_OK;
}

HRESULT CNcFolder::CheckDul(LPCTSTR pDisplayName,int datatype)
{
	USES_CONVERSION;
	WIN32_FIND_DATA fd;
	char tmp[MAX_PATH] ;
	if(FindFirstFile(pDisplayName,&fd)==INVALID_HANDLE_VALUE)
	{
		return E_FAIL;
	}
	ISFSError err;
	//LPCTSTR pstrFileName ;
//	TCHAR szTempTitle[MAXNAMELEN+1];
	TCHAR szSubVol[MAXNAMELEN+1];

	switch(datatype)
	{
	case BOOK_DATA:
		strcpy(szSubVol,_T("book"));
		strcpy(tmp,fd.cFileName);
		break;
	case MUSIC_DATA:
		strcpy(szSubVol,_T("music"));
		break;
	default:
		strcpy(szSubVol,_T("photo"));
		strcpy(tmp,_T(fd.cFileName));
		break;
	}
	TCHAR szBuf[MAX_TOTAL_SIZE];
	TCHAR * pData;
	ncfileinfo *finfo;
	finfo=(ncfileinfo *)malloc(sizeof(ncfileinfo ));
	int num;
	
	memset(szBuf,0,sizeof(TCHAR)*MAX_TOTAL_SIZE);
	if(mediaFsOpened())
	err=ISFS_ReadDir((const u8*)szSubVol,NULL, (u32*)&num);
	if(num>0)
	err=ISFS_ReadDir((const u8*)szSubVol,(u8*)szBuf, (u32*)&num);
	if(err<0)
	{
		ATLTRACE(_T("Error: _CountFilesInFolder() read directory info failed!\r\n"));
		return E_FAIL;
	}
	pData=szBuf;
	for(int i=0;i<num;i++)
	{
		TCHAR szFileName[MAXNAMELEN];
		memset(szFileName,0,sizeof(TCHAR)*MAXNAMELEN);
		_tcscpy(szFileName,pData);
		if( _tcscmp(szFileName, _T("."))==0 ) 
			continue;
		if( _tcscmp(szFileName, _T(".."))==0 ) 
			continue;
		TCHAR szSrcFile[MAX_PATH];
		::wsprintf(szSrcFile, _T("%s/%s"), szSubVol, szFileName);
		
			IOSFd hFile=ISFS_Open((const u8*)szSrcFile, ISFS_READ_ACCESS);
			if(hFile<0)
			{
				if(mediaFsOpened())
					mediaFsClose();
				return E_FAIL;
			}
			
			GetDisplayNameOf(hFile, finfo,datatype);
			err=ISFS_Close(hFile);
			if(err<0)
			{
				if(mediaFsOpened())
					mediaFsClose();
				return E_FAIL;
			}
			if(_tcsncmp((char*)tmp,_T(finfo->filename),sizeof(finfo->filename))==0)
			{
			//	_tcscpy((char *)pRealName,szSrcFile);
				//MessageBox(NULL,_T("fond"),_T("sadf"),MB_OK);
				return S_OK;
			}
		
		while(*pData!=0)
		{
			pData=::CharNext(pData);
		}
		*pData=_T('e');  //replace the EOF with 'e' , so the next CharNext() calling will work.
		pData=::CharNext(pData);
	}
	return E_FAIL;
}

HRESULT CNcFolder::disp2real(LPCTSTR pDisplayName,LPCTSTR pRealName, int datatype)
{
	USES_CONVERSION;

	ISFSError err;
	//LPCTSTR pstrFileName ;
//	TCHAR szTempTitle[MAXNAMELEN+1];
	TCHAR szSubVol[MAXNAMELEN+1];

	switch(datatype)
	{
	case BOOK_DATA:
		strcpy(szSubVol,_T("book"));
		break;
	case MUSIC_DATA:
		strcpy(szSubVol,_T("music"));
		break;
	default:
		strcpy(szSubVol,_T("photo"));
		break;
	}
	TCHAR szBuf[MAX_TOTAL_SIZE];
	TCHAR * pData;
	ncfileinfo *finfo;
	finfo=(ncfileinfo *)malloc(sizeof(ncfileinfo ));
	int num;
	
	memset(szBuf,0,sizeof(TCHAR)*MAX_TOTAL_SIZE);
	if(mediaFsOpened())
	err=ISFS_ReadDir((const u8*)szSubVol,NULL, (u32*)&num);
	if(num>0)
	err=ISFS_ReadDir((const u8*)szSubVol,(u8*)szBuf, (u32*)&num);
	if(err<0)
	{
		ATLTRACE(_T("Error: _CountFilesInFolder() read directory info failed!\r\n"));
		return E_FAIL;
	}
	pData=szBuf;
	for(int i=0;i<num;i++)
	{
		TCHAR szFileName[MAXNAMELEN];
		memset(szFileName,0,sizeof(TCHAR)*MAXNAMELEN);
		_tcscpy(szFileName,pData);
		if( _tcscmp(szFileName, _T("."))==0 ) 
			continue;
		if( _tcscmp(szFileName, _T(".."))==0 ) 
			continue;
		TCHAR szSrcFile[MAX_PATH];
		::wsprintf(szSrcFile, _T("%s/%s"), szSubVol, szFileName);
		
			IOSFd hFile=ISFS_Open((const u8*)szSrcFile, ISFS_READ_ACCESS);
			if(hFile<0)
			{
				if(mediaFsOpened())
					mediaFsClose();
				return E_FAIL;
			}
			
			GetDisplayNameOf(hFile, finfo,datatype);
			err=ISFS_Close(hFile);
			if(err<0)
			{
				if(mediaFsOpened())
					mediaFsClose();
				return E_FAIL;
			}
			if(_tcsncmp((char*)pDisplayName,_T(finfo->filename),sizeof(finfo->filename))==0)
			{
				_tcscpy((char *)pRealName,szSrcFile);
				//MessageBox(NULL,_T("fond"),_T("sadf"),MB_OK);
				return S_OK;
			}
		
		while(*pData!=0)
		{
			pData=::CharNext(pData);
		}
		*pData=_T('e');  //replace the EOF with 'e' , so the next CharNext() calling will work.
		pData=::CharNext(pData);
	}
	return E_FAIL;
}
int ConvertAnsiToUnicode(const CString &str1,const CString &str2)
{
	UINT nCodePage = 936; 
	CFile file(str1,CFile::modeRead);
	int iFileLen = file.GetLength ();
	WORD tag;
	file.Read(&tag,2);
	if(tag==0xFEFF)
	{
		return 0;//don't need convert
		//MessageBox("This file is unicode file ,needless to convert!");
	}

	CString dp;
	char *pMultiByteStr = new char[iFileLen]; 
	file.SeekToBegin();
	file.Read (pMultiByteStr, iFileLen);
	dp=_T(pMultiByteStr);
	dp=dp.Left(iFileLen);
	file.Close();	
	//IsTextUnicode();
	//------
	int nLength=MultiByteToWideChar(nCodePage,0,dp,-1,NULL,0);
	wchar_t* pBuffer = new wchar_t[nLength+1];
	MultiByteToWideChar(nCodePage,0,dp,-1,pBuffer,nLength);
	pBuffer[nLength]=0;
	CFile pp(str2,CFile::modeCreate|CFile::modeWrite);

	WORD dw=0xFEFF;
	pp.Write(&dw,2);
	pp.Write(pBuffer,(nLength+1)*2);
	pp.Close();
	return 1;
}


void FormatBookFile(const CString &str1)
{
	CFile m_file(str1,CFile::modeRead);
	int iFileLen = m_file.GetLength ();
	int pixcnt=0;
	int i=1;
	WORD bk1 = 0x000D;
	WORD bk2 = 0x000A;
	//int iFileLen = m_file.GetLength ();
	WCHAR *buffer = new WCHAR[iFileLen/2];
	//PSTR buffer = new char[iFileLen];
	//int kk=wcscmp(L"A",L"A");
	m_file.Read (buffer, iFileLen);

	m_file.Close();
	unlink( str1);
	CFile dest(str1,CFile::modeCreate|CFile::modeWrite);
	dest.Write(buffer,2);//write head
	do
	{
		if((buffer[i]>=48 && buffer[i] <=57)||(buffer[i]>=65 && buffer[i] <=90)||
			(buffer[i]>=97 && buffer[i] <=122)||(buffer[i]>=65296 && buffer[i] <=65305)||
			(buffer[i]>=65313 && buffer[i] <=65338)||(buffer[i]>=65345 && buffer[i] <=65370) )
		{
			pixcnt = pixcnt +7;
		}
		else if(buffer[i] == 32)
		{
			pixcnt = pixcnt +4;
		}
		else if(buffer[i] == 13||buffer[i] == 10)
		{
               //  buffer[i] = 32;
		   pixcnt = 0;
		}
		else
		{
			pixcnt = pixcnt +13;
		}
		if(pixcnt >=240)
		{
			pixcnt=0;
			dest.Write(&bk1,2);
			dest.Write(&bk2,2);	
			//pixcnt=0;
		}
		else
		{
			dest.Write((LPCWSTR)(buffer+i),2);
			i++;
		}

	}while (i<iFileLen/2);
	//dest.Rename();
	delete buffer;
	dest.Close();
}



int CNcFolder::ConvertSourceFile(LPCTSTR pstrSource,TCHAR pstrConverted[MAX_PATH],int datatype)
{
	CString tmpsrcpath;
	CString tmpname;
	CString tmpdestpath;
	WIN32_FIND_DATA fd;
	 int pMp3StartOffset;
	 

	tmpsrcpath.Format("%s",pstrSource);
	tmpdestpath.Format("%s",pstrConverted);
	if (datatype==1)//book
	{
		CString tmpstr =tmpsrcpath.Right(3);
		char tmp[5];
		strcpy(tmp,tmpstr);
		tmpstr = strlwr(tmp);
		if(tmpstr == "txt")
		{
			FindFirstFile(tmpsrcpath,&fd);
			tmpdestpath = tmpdestpath+"\\"+fd.cFileName;
			//ansi convert to unicode
			if(ConvertAnsiToUnicode(tmpsrcpath,tmpdestpath)==0)
			{
				return 0;	
			}
			else
			{
				FormatBookFile(tmpdestpath);
				strcpy(pstrConverted,tmpdestpath);
				return 1;
			}
		}
		MessageBox(NULL,_T("添加文件失败，系统无法支持该文件类型！"),_T("错误"),MB_OK);
		return -1;
	}
	if (datatype==2)//music
	{
			if(!_IsMPEGV1L3File(pstrSource, &pMp3StartOffset))
		return -1;

		//need to convert
		char tmpstr[5];
		strcpy(tmpstr,tmpsrcpath.Right(3));
		strcpy(tmpstr,strlwr(tmpstr));
		if((_tcscmp(tmpstr,_T("mp3"))==0))
		{
			return 0;
		}
		TCHAR szParams[MAX_PATH*2] ;
		FindFirstFile(tmpsrcpath,&fd);
		tmpname.Format("%s",fd.cFileName);
		tmpsrcpath=tmpsrcpath.Left(tmpsrcpath.GetLength()-tmpname.GetLength());
		
		tmpname=tmpname.Left(tmpname.GetLength()-3)+"mp3";
		::wsprintf(szParams," %s %s %s %s ",fd.cFileName,tmpname,tmpsrcpath,tmpdestpath);	
		
		DWORD dwExitCode ;
		PROCESS_INFORMATION pi;
		STARTUPINFO si = {sizeof(si)};
		si.dwFlags=STARTF_USESHOWWINDOW;
		si.wShowWindow=SW_HIDE;
//		
		char workpath[MAX_PATH];
		CString dllpath;
		GetWorkPath(workpath);
		dllpath.Format(("%s"),workpath);
		dllpath.TrimRight("uninst.exe");
		dllpath = dllpath+"tomp3.exe";
		BOOL ret = CreateProcess( dllpath, szParams,NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
				if (ret) 
				{
					CloseHandle(pi.hThread);
					WaitForSingleObject(pi.hProcess, INFINITE);
					GetExitCodeProcess(pi.hProcess, &dwExitCode);
					CloseHandle(pi.hProcess);
				}
				else
				{
					free(szParams);
					::_endthread();
					return S_OK;
				}
		sprintf(pstrConverted,"%s\\%s",tmpdestpath,tmpname);

	}
	if (datatype==3)//photo
	{
		TCHAR pSufix[10];
		memset(pSufix,0,sizeof(TCHAR)*10);

		FindFirstFile(tmpsrcpath,&fd);
		tmpsrcpath=tmpsrcpath.Left(tmpsrcpath.GetLength() - strlen(fd.cFileName));//??
		if(img2gba((const char*)fd.cFileName,tmpsrcpath,tmpdestpath) <0)
			return -1;
		tmpdestpath = tmpdestpath + "\\" + fd.cFileName;
		GetLastDotPos(tmpdestpath,pSufix);
		tmpdestpath=tmpdestpath.Left(tmpdestpath.GetLength()-strlen(pSufix));
		tmpdestpath=tmpdestpath+"imb";
		strcpy(pstrConverted , tmpdestpath);
	}
	
	return 1;
}

HRESULT CNcFolder::AddFile(LPCTSTR pstrSource, int datatype)
{
	LPCTSTR realname;
	ATLASSERT(pstrSource);
	if( *pstrSource==_T('\0') ) 
		return E_FAIL;	

	TCHAR szSubVol[MAX_PATH];
	TCHAR szDestPath[MAX_PATH];
	//check file type
	TCHAR WindowTemp[]=_T("\\temp");
	TCHAR szWindowsPath[MAX_PATH];
	//check file already in nc
	if(CheckDul(pstrSource,datatype)==S_OK)
	{
		MessageBox(NULL,"当前文件在聚乐卡上已经存在，要覆盖原有文件吗?","",MB_YESNO);
		return S_OK;
	}
	//end 
	::GetWindowsDirectory(szWindowsPath,MAX_PATH);
	_tcscat(szWindowsPath,WindowTemp);
	//convert file format
	int errint=ConvertSourceFile(pstrSource,szWindowsPath,datatype);
	if (errint<0)//
	{
		return S_FALSE;
	}
	else if(errint>0)//needn't convert
	{
		_tcscpy((char *)pstrSource,szWindowsPath);
	}
	
	// Get the file's attributes
	DWORD dwFileAttribs = ::GetFileAttributes(pstrSource);
	//get info of source file
	WIN32_FIND_DATA mFileInfo;
	HANDLE hFind=INVALID_HANDLE_VALUE;
	hFind=FindFirstFile(pstrSource,&mFileInfo);
	if(hFind==INVALID_HANDLE_VALUE)
	{
		MessageBox(NULL,_T("File not found!"),_T("Warring"),MB_OK);
		return E_FAIL;
	}
	//check free card space
	ISFSStats stats;
	ISFSError err =ISFS_GetStats(&stats);
	if(err<0)
	{
		ATLTRACE(_T("Error: ISFS_EOF read file state failed!\r\n"));
		return E_FAIL;
	}
	if(mFileInfo.nFileSizeLow > (stats.freeBlocks-256)*16384)//游工部保留4M，不可用
	{
		MessageBox(NULL,"iQue聚乐卡剩余空间不足！","错误",MB_OK);
		return E_FAIL;
	}
	// Open the PC file and copy it to the NC device
	CFile f;
	if( f.Open(pstrSource,CFile::modeRead )==FALSE ) 
	{
		if(mediaFsOpened())
			mediaFsClose();
		return E_FAIL;
	}

	// Create the new file in NC
	IOSFd file;
	//ISFSError err;
	TCHAR szRealName[MAX_PATH];
	TCHAR szDestName[MAX_PATH];
	//get vol
	switch(datatype)
	{
	case BOOK_DATA:
		strcpy(szSubVol,_T("book"));
		break;
	case MUSIC_DATA:
		strcpy(szSubVol,_T("music"));
		break;
	default:
		strcpy(szSubVol,_T("photo"));
		break;
	}
	//trim sour filename
	CString dispname;
	//if(strlen(mFileInfo.cFileName) >15)
	//{
		//dispname.Format("%s",_T(mFileInfo.cFileName));
		//dispname=dispname.Mid(0,10)+dispname.Right(4);
		//MessageBox(NULL,_T("文件名太长"),_T("警告"),MB_OK);
		//return E_FAIL;
//	}
	_tcscpy(szRealName,_T(mFileInfo.cFileName ));
	::_FindUniqueRealFileName(szSubVol,szRealName);
	::wsprintf(szDestPath,_T("%s/%s"),szSubVol,szRealName);
	//::wsprintf(szDestPath,_T("%s/%s"),"book","12.txt");
	//MessageBox(NULL,szDestPath,"szDestPath ll",MB_OK);
	err=ISFS_CreateFile((const u8*)szDestPath, FILE_ATTRIBUTE_NORMAL, ISFS_RW_ACCESS, ISFS_RW_ACCESS, ISFS_RW_ACCESS);
	if(err<0&&err!=ISFS_ERROR_EXISTS)
	{
		if(mediaFsOpened()) mediaFsClose();
		f.Close();
		return E_FAIL;
	}
	//open the file in NC 
	if( (file=ISFS_Open((const u8*)szDestPath, ISFS_RW_ACCESS))<0) 
	{
		if(mediaFsOpened())
			mediaFsClose();
		f.Close();
		return E_ACCESSDENIED;
	}
	//if the file is .mp3 file , we needn't change the write position .
	//for the other file type , we should write from 32B offset .
	_SetFileWritePos(&f,file,szRealName);
//	::CopyData(file,&f,mFileInfo.nFileSizeLow);
	//-------->copy data from  
	CFileCopyProgress dlg;
		dlg.pPcFd=&f;
		dlg.ncFd=file;
		dlg.NCFlag=1;//pc2nc
		dlg.fsize=mFileInfo.nFileSizeLow;
	
	//dlg.m_pstrFileName=szDestName; //
	UINT res=dlg.DoModal();	
	if(res==IDCANCEL)
   	{		
		err=ISFS_Delete((const u8 *)szDestPath);
		return E_FAIL;
   	}

	//////////////////////////////////////////////////////////////////////////
	//strcpy(szDestPath,"music/1.mp3");
	if( (file=ISFS_Open((const u8*)szDestPath, ISFS_RW_ACCESS))<0) 
	{
		if(mediaFsOpened())
			mediaFsClose();
		f.Close();
		return E_ACCESSDENIED;
	}
		//	ISFSError err;
	//u8 buf[2];
	USES_CONVERSION;
	//memset(buf,0,2);
	//_tcscpy((char*)_T(buf),(const char*)A2CW(pDisplayName));
	err=ISFS_Seek(file, 0, SEEK_SET);
	//<--------
	//Write the display file name into the file .
	::wsprintf(szDestName,_T("%s"),_T(mFileInfo.cFileName));
	//need to trim destfilename
	TCHAR pSufix[10];
	CString tmpdestname;
	
	memset(pSufix,0,sizeof(TCHAR)*10);
	GetLastDotPos(szDestName,pSufix);
	int tmplen=MAX_FILENAME-strlen(pSufix)-1;
	tmpdestname=szDestName;

	//文件名长度修正，最多15个汉字
	UINT nCodePage = 936;
	if(tmpdestname.GetLength() >=MAX_FILENAME)
	{
		tmpdestname.TrimRight(pSufix);
		tmpdestname.TrimRight(".");
		int nLength=MultiByteToWideChar(nCodePage,0,tmpdestname,-1,NULL,0);
		wchar_t* pBuffer = new wchar_t[11];
		MultiByteToWideChar(nCodePage,0,tmpdestname,-1,pBuffer,10);
		pBuffer[10]=0;
		tmpdestname=W2CT(pBuffer);
		tmpdestname=tmpdestname+"."+pSufix;
	}
	_WriteDisplayFileName(file,szRealName,tmpdestname,COPY_TYPE);
	
	f.Close();
	err=ISFS_Close(file);
	if(err<0)
	{
		if(mediaFsOpened())
			mediaFsClose();
		return E_FAIL;
	}
	// Set the new file attributes
	DWORD dwAccess = 0;
	if( dwFileAttribs & FILE_ATTRIBUTE_READONLY )
		dwAccess |= FILE_ATTRIBUTE_READONLY;
	if( dwFileAttribs & FILE_ATTRIBUTE_HIDDEN ) 
		dwAccess |= FILE_ATTRIBUTE_HIDDEN;
	if( dwFileAttribs & FILE_ATTRIBUTE_ARCHIVE ) 
		dwAccess |= FILE_ATTRIBUTE_ARCHIVE;
	ISFS_SetAttr((const u8*)szDestPath, NULL, NULL,dwAccess,NULL, NULL, NULL);

	
	//if(mediaFsOpened())
	//	mediaFsClose();
//	MessageBox(NULL,_T("add ok"),_T("ss"),MB_OK);
	return S_OK;
}
HRESULT CNcFolder::DelFile(LPCTSTR pstrFileName,int datatype)
{
//	ISFSError err;
//	int filecount;
	HRESULT hr;
	TCHAR realname[MAX_PATH];
	hr=disp2real(pstrFileName,realname,datatype);
	
	if(ISFS_Delete((const u8*)realname)<0)
		return E_FAIL;

	return S_OK;
}
HRESULT CNcFolder::GetObjectList(int datatype,TCHAR OnjList[USB_BUF_SIZE])
{
	USES_CONVERSION;

	ISFSError err;

	TCHAR szSubVol[MAXNAMELEN+1];

	switch(datatype)
	{
	case BOOK_DATA:
		strcpy(szSubVol,_T("book"));
		break;
	case MUSIC_DATA:
		strcpy(szSubVol,_T("music"));
		break;
	default:
		strcpy(szSubVol,_T("photo"));
		break;
	}
	TCHAR szBuf[MAX_TOTAL_SIZE];
	TCHAR * pData;
	ncfileinfo *finfo;
	finfo=(ncfileinfo *)malloc(sizeof(ncfileinfo ));
	int num;

	memset(szBuf,0,sizeof(TCHAR)*MAX_TOTAL_SIZE);
	if(mediaFsOpened())
		err=ISFS_ReadDir((const u8*)szSubVol,NULL, (u32*)&num);
	if(num>0)
		err=ISFS_ReadDir((const u8*)szSubVol,(u8*)szBuf, (u32*)&num);
	if(err<0)
	{
		ATLTRACE(_T("Error: _CountFilesInFolder() read directory info failed!\r\n"));
		return E_FAIL;
	}
	
	pData=szBuf;
	int k=strlen(szBuf);
		for(int i=0;i<num;i++)
		{
			wsprintf(OnjList,"%s",pData);
			//_tcscat(OnjList,pData);
			while(*pData!=0)
			{
				pData=::CharNext(pData);
			}
			*pData=_T('e');  //replace the EOF with 'e' , so the next CharNext() calling will work.
			pData=::CharNext(pData);
		}
		//_tcscpy(OnjList,pData);
		return S_OK;
}