//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "GlobalUnit.h"
#include "Project.h"
#include "StyleItem.h"
#include "MidiTrack.h"
#include "Undo.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)


typedef struct tagTempStyleMap  //临时风格映射
{
	UINT idTemp;
	UINT idLoc;
	UINT idStyle;
} TTempStyleMap, *PTTempStyleMap;

const char 	*g_strProjError[11] = {
			"全局或部分音色库失效，使用缺省音色库",
			"部分段落风格失效，使用全局风格替换",
			"部分音效失效，请重新设置",
			"打开工程失败！\n\n文件不存在",
			"打开工程失败！\n\n早期版本，请尝试用大众版打开",
			"打开工程失败！\n\n版本太新，请更新软件到最新版",
			"打开工程失败！\n\n无法识别的版本号",
			"打开工程失败！\n\n文件已损坏",
			"打开工程失败！\n\n音频数据被破环",
			"打开工程失败！\n\n使用的风格未下载或已失效",
			"打开工程失败！\n\n使用本地风格须先登录"};

const DWORD g_dwProjectVersion = MAKELONG(7, 5); //ver 5.6
//ver 2.0-2.1 3.0-3.1 4.0-4.1 5.0-5.1禁用，以判断早期版本
//ver 3.2 专业版工程
//ver 3.3 g_bPredefine读写，支持无Audio
//ver 4.2 TPPRSTYLE风格结构，支持自制风格/支付记录
//ver 4.3 支持变调，新TBar/TOpusStage结构
//ver 4.4 g_bMidiMelody读写
//ver 5.2 VIP版工程, 记录工程功能费支付，旋律识别信息更新, 不保存TTrack信息，原始段落表
//ver 5.3 增加工程模式标志 iMode=0,1,2
//ver 5.4 TTrack保存iBank
//ver 5.5 增加ExtendFont
//ver 5.6 新BaseTrack格式
//ver 5.7 音频轨道增加到17轨

vector<TTempStyleMap*> u_aTempStyleMap; //临时风格映射表
wstring g_strLastProjSavePath,			// 上次保存工程路径
		g_strProjectName, 				// 工程文件名
		g_strAutoProjName;				// 自动保存文件名
		//g_strFontFile_SVD;		// 音色库文件名(已保存)

vector<wstring>g_lstRecentProject; 		// 最近的工程文件
HANDLE g_hProjectEvent; // 工程文件读写互斥变量

int		g_iMelodyKey_SVD = -1,		// 主旋律调号(已保存)
		g_nMelodyTempo_SVD = 75;		// 主旋律速度(已保存)

float	g_fRecordVolume_SVD = -1,		//录音音量(已保存)
		g_fSpeakerVolume_SVD = -1;		//播放音量(已保存)

char	g_strSoundFont_SVD[80];	//全局音色库名(已保存)

TUndoLite* u_pProjLite = NULL,
		* u_pAutoLite = NULL;

void ClearProjStyleMap()
{
	for( int i=0; i<u_aTempStyleMap.size(); i++ ){
		delete u_aTempStyleMap[i];
	}

	u_aTempStyleMap.clear();

	u_pAutoLite = u_pProjLite = NULL;
}

TPROSTYLE* CheckStyle( int idLoc, int idStyle )
{
	TPROSTYLE* pStyle = GetStyleInfo( idLoc, idStyle );

	if( pStyle && idLoc==0 && pStyle->pOrigin->state!=e_Downloaded ){
		if( f_CS_DownloadStyle( idStyle, NULL )!=0 ){
			pStyle = NULL;
		}
		else{
			pStyle->pOrigin->state = e_Downloaded;
		}
	}

	return pStyle;
}

void UpdateRecentProject(wstring wstrProj)
{
	// 更新最近工程列表
	wchar_t strTemp[MAX_PATH];

	wstring strLowerProjName, strLowerCompName;
	wcscpy(strTemp, wstrProj.c_str());
	strLowerProjName = _wcslwr(strTemp);

	BOOL bInList = FALSE;
	for (int i = 0; i < g_lstRecentProject.size(); i++) {
		wcscpy(strTemp, g_lstRecentProject[i].c_str());
		strLowerCompName = _wcslwr(strTemp);
		if (strLowerProjName.compare(strLowerCompName) == 0) {
			if (i > 0) {
				vector<wstring>::iterator iterStr =
					g_lstRecentProject.begin() + i;
				g_lstRecentProject.erase(iterStr);
				g_lstRecentProject.insert(g_lstRecentProject.begin(),
											wstrProj);
			}

			bInList = TRUE;

			break;
		}
	}

	if (!bInList) {
		g_lstRecentProject.insert(g_lstRecentProject.begin(),
						wstrProj);
	}
}

void CheckLocId( UINT& idLoc, UINT& idStyle )
{
	if( idLoc==(UINT)-1 ){
		for( int k=0; k<u_aTempStyleMap.size(); k++ ){
			if( idStyle==u_aTempStyleMap[k]->idTemp ){
				idLoc = u_aTempStyleMap[k]->idLoc;
				idStyle = u_aTempStyleMap[k]->idStyle;

				break;
			}
		}
	}
}

void KeepLocSegment( LOCSEGLIST& aLocSegs, UINT& idLoc, UINT& idStyle,
												int iSegType, int iSegNo )
{
	bool bKeep = false;
	DWORD dwSeg = MAKELONG( iSegType, iSegNo );
	for( int k=0; k<aLocSegs.size(); k++ ){
		if( idLoc==aLocSegs[k]->idLoc
					&& idStyle==aLocSegs[k]->idStyle ){
			for( int t=0; t<aLocSegs[k]->aSegs.size(); t++ ){
				if( dwSeg==aLocSegs[k]->aSegs[t] ){
					bKeep = true;
					break;
				}
			}

			if( !bKeep ){
				aLocSegs[k]->aSegs.push_back( dwSeg );
				bKeep = true;
				break;
			}
		}
	}

	if( !bKeep ){
		TLocSegment* pLocSeg = new TLocSegment;
		pLocSeg->idLoc = idLoc;
		pLocSeg->idStyle = idStyle;
		pLocSeg->aSegs.push_back( dwSeg );
		aLocSegs.push_back( pLocSeg );
	}

	CheckLocId( idLoc, idStyle );
}

void SaveOpusStages( TOpusStageList& lstStages, LOCSEGLIST& lstLocSeg, FILE* pFile )
{
	int num = lstStages.size();
	fwrite( &num, sizeof(int), 1, pFile );

	for( int i=0; i<num; i++ ){
		TOpusStage* pStage = lstStages[i];
		fwrite( &pStage->iSegType, sizeof(char), 1, pFile );
		fwrite( &pStage->iSegNo, sizeof(char), 1, pFile );
		fwrite( &pStage->iSegKey, sizeof(char), 1, pFile );
		fwrite( &pStage->nVol, sizeof(char), 1, pFile );

		int count = pStage->aBars.size();
		fwrite( &count, sizeof(int), 1, pFile );

		for( int j=0; j<count; j++ ){
			TBar* pBar = pStage->aBars[j];
			fwrite( &pBar->aChords, sizeof(TBarChords), 1, pFile );
			fwrite( &pBar->iBarKey, sizeof(char), 1, pFile );
		}
		count = pStage->aTracks.size();
		fwrite( &count, sizeof(int), 1, pFile );

		for( int j=0; j<count; j++ ){
			TTrack* pTrack = pStage->aTracks[j];
			UINT idLoc = pTrack->iStyleLoc,
				idStyle = pTrack->iStyleId;

			//记录本地风格片段
			if( idLoc!=0 ){
				KeepLocSegment( lstLocSeg, idLoc, idStyle, pStage->iSegType, pTrack->iSegNo );
			}

			fwrite( &idLoc, sizeof(UINT), 1, pFile );
			fwrite( &idStyle, sizeof(UINT), 1, pFile );
			fwrite( &pTrack->iSegNo, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iChanNo, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iChanSpec, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iProg, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iProgOrig, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->nVol, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->nVolOrig, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iBank, sizeof(BYTE), 1, pFile );
			fwrite( &pTrack->iFile, sizeof(BYTE), 1, pFile );
		}
	}
}

BOOL SaveProject( LPCSTR strProjectName, int iSaveMode, HWND hNotifyWnd )
{
	wstring wstrProj = str2wstr( strProjectName );
	DebugPrint("Saving project: %s...", strProjectName);

	WaitForSingleObject(g_hProjectEvent, INFINITE);

	BOOL bSuccess = FALSE;
	FILE *pFile = NULL;

	if ((pFile = fopen( strProjectName, "w+b" )) != NULL) {
		UINT lFileSize = 0;
		fpos_t posFileSize = 0;

		// 保存版本号
		fwrite(&g_dwProjectVersion, sizeof(DWORD), 1, pFile);

		// 预留文件长度
		fgetpos(pFile, &posFileSize);
		fwrite(&lFileSize, sizeof(UINT), 1, pFile);

		// 保存模式标志
		fwrite(&iSaveMode, sizeof(int), 1, pFile);

		// 旋律主要信息
		fwrite(&g_iMelodyTimeSignature, sizeof(int), 1, pFile); // 拍号
		fwrite(&g_nMelodyTempo, sizeof(int), 1, pFile); // 速度
		fwrite(&g_iMelodyKey, sizeof(int), 1, pFile); // 调号

		// 全局音色库
		//string strFont = wstr2str( g_strFontFile );
		string strFontUTF8 = GBToUTF8( g_strSoundFont );//strFont.c_str() );
		int nFontNameLen = strFontUTF8.length() + 1;
		fwrite(&nFontNameLen, sizeof(int), 1, pFile);
		fwrite( strFontUTF8.c_str(), sizeof(char), nFontNameLen, pFile);

		fwrite( &g_bExtFont, sizeof(bool), 1, pFile );

		// 各项音量设值
		fwrite(&g_fRecordVolume, sizeof(float), 1, pFile);
		fwrite(&g_fSpeakerVolume, sizeof(float), 1, pFile);
		fwrite(&g_fMusicVolume, sizeof(float), 1, pFile);

		int iMute = g_bComposeMute ? 1 : 0;
		fwrite(&iMute, sizeof(int), 1, pFile);

		LOCSEGLIST aLocSegs;  //使用的本地风格片段列表
		// Theme
		g_Theme.WriteProj( aLocSegs, pFile );
		// Opus
		g_Opus.WriteProj( aLocSegs, pFile );
		// MidiTrack
		g_Midi.WriteProj( pFile );

		//保存使用的音源
		vector<BYTE> lstBank;
		g_Theme.GetSpecBanks( lstBank );
		g_Midi.GetSpecBanks( lstBank );
		//g_Opus.GetSpecBanks( lstBank );

		int nCount = lstBank.size();
		fwrite(&nCount, sizeof(int), 1, pFile);
		for( int i=0; i<nCount; i++ ){
			BYTE iBank = lstBank[i];
			fwrite(&iBank, sizeof(BYTE), 1, pFile);

			if( iBank<0x80 ){
				char* strFontName = g_lstFonts[iBank]->strFontName;
				BYTE len = strlen( strFontName );

				fwrite(&len, sizeof(BYTE), 1, pFile);
				fwrite( strFontName, sizeof(char), len, pFile);
			}
			else{
/*				char* name = strrchr(g_lstVSTi[iBank-0x80]->strFileName, '\\' ) + 1,
					*ext = strrchr( g_lstVSTi[iBank-0x80]->strFileName, '.' );
				BYTE len = ext>name ? ext - name : strlen(name);
*/
				DWORD uniqueID = g_lstVSTi[iBank-0x80]->uniqueID;
				fwrite( &uniqueID, sizeof(DWORD), 1, pFile );
//				fwrite(&len, sizeof(BYTE), 1, pFile);
//				fwrite( name, sizeof(char), len, pFile);

				BYTE cmprMem[100000];
				int lenMem = 100000;

				if( f_MM_HandleVSTiPreset( iBank, lenMem, cmprMem, false )==S_OK ){
					fwrite( &lenMem, sizeof(int), 1, pFile );
					fwrite( cmprMem, 1, lenMem, pFile );
				}
				else{
					lenMem = 0;
					fwrite( &lenMem, sizeof(int), 1, pFile );
				 }
			}
		}

		// Audio
		if( iSaveMode==PROJ_MODE_UPLOAD ){
			int num = 0;
			fwrite( &num, sizeof(int), 1, pFile );
		}
		else{
			g_Audio.WriteProj( pFile );
		}

		//PreStylePanel
		TStyleItem* pSty = g_pPreStyle;

		UINT idLoc = 0, idStyle = 0;
		if( pSty->pStyle ){
			idLoc = pSty->pStyle->idLoc;
			idStyle = pSty->pStyle->idStyle;

			CheckLocId( idLoc, idStyle );
		}

		fwrite( &idLoc, sizeof(UINT), 1, pFile );
		fwrite( &idStyle, sizeof(UINT), 1, pFile );

		int num = pSty->aItems->Count;
		fwrite( &num, sizeof(int), 1, pFile );
		for( int i=0; i<num; i++ ){
			TSegmentItem* pSeg = (TSegmentItem*)pSty->aItems->Items[i];

			fwrite( &pSeg->iSegType, sizeof(char), 1, pFile );
			fwrite( &pSeg->iSegNo, sizeof(char), 1, pFile );
			fwrite( &pSeg->volume, sizeof(char), 1, pFile );
			fwrite( &pSeg->nBars, sizeof(int), 1, pFile );

			int count = pSeg->aItems->Count;
			fwrite( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				TTrackItem* pTrk = (TTrackItem*)pSeg->aItems->Items[j];
				TTrack* pTrack = pTrk->pTrack;
				UINT idLoc = pTrack->iStyleLoc,
					idStyle = pTrack->iStyleId;

				CheckLocId( idLoc, idStyle );

				fwrite( &idLoc, sizeof(UINT), 1, pFile );
				fwrite( &idStyle, sizeof(UINT), 1, pFile );

				fwrite( &pTrack->iSegNo, sizeof(char), 1, pFile );
				fwrite( &pTrack->iChanNo, sizeof(char), 1, pFile );
				fwrite( &pTrack->iChanSpec, sizeof(char), 1, pFile );
				fwrite( &pTrack->iProg, sizeof(char), 1, pFile );
				fwrite( &pTrack->iProgOrig, sizeof(char), 1, pFile );
				fwrite( &pTrack->nVol, sizeof(char), 1, pFile );
				fwrite( &pTrack->nVolOrig, sizeof(char), 1, pFile );
			}
		}

		//段落预设
		fwrite( &g_iPreStage, sizeof(int), 1, pFile );
		//视图模式
		int iContentView = 0;
		Application->MainForm->Perform( UM_GETCONTENTVIEW, (NativeInt)&iContentView, 0 );
		fwrite(&iContentView, sizeof(int), 1, pFile);
		//预设工程
		fwrite( &g_bPredefine, sizeof(bool), 1, pFile );
		//MIDI输入工程
		fwrite( &g_bMidiMelody, sizeof(bool), 1, pFile );

		//保存本地风格数据
		num = aLocSegs.size();
		fwrite( &num, sizeof(int), 1, pFile );

		for( int i=0; i<aLocSegs.size(); i++ ){
			TLocSegment* pLocSeg = (TLocSegment*)aLocSegs[i];

			int nSegNum = pLocSeg->aSegs.size();
			WORD (*aSegs)[2] = new WORD[nSegNum][2];

			for( int j=0; j<pLocSeg->aSegs.size(); j++ ){
				aSegs[j][0] = LOWORD( pLocSeg->aSegs[j] );
				aSegs[j][1] = HIWORD( pLocSeg->aSegs[j] );
			}

			int len = 1000000;
			BYTE* mem = new BYTE[1000000];
			UINT idLoc = pLocSeg->idLoc,
				idStyle = pLocSeg->idStyle;

			if( idLoc==(UINT)-1 ){
				for( int k=0; k<u_aTempStyleMap.size(); k++ ){
					if( idStyle==u_aTempStyleMap[k]->idTemp ){
						idLoc = u_aTempStyleMap[k]->idLoc;
						idStyle = u_aTempStyleMap[k]->idStyle;

						break;
					}
				}
			}

			fwrite( &idLoc, sizeof(UINT), 1, pFile );
			fwrite( &idStyle, sizeof(UINT), 1, pFile );

			f_CM_ProjBackupStyle( pLocSeg->idLoc, pLocSeg->idStyle,
														nSegNum, aSegs, len, mem );

			fwrite( &len, sizeof(int), 1, pFile );
			if( len>0 )
				fwrite( mem, 1, len, pFile );

			delete[] mem;
			delete[] aSegs;
			delete aLocSegs[i];
		}

		aLocSegs.clear();

		// 保存文件长度
		lFileSize = ftell(pFile);

		fclose( pFile );

		int lCSSize = f_CS_SaveProject( strProjectName );
		if( lCSSize>0 ){
			lFileSize += lCSSize;
		}

		long lMMSize = f_MM_SaveProject( iSaveMode, hNotifyWnd, strProjectName );

		if( lMMSize>0 ){
			lFileSize += lMMSize;
		}

		pFile = fopen( strProjectName, "r+b" );
		fsetpos(pFile, &posFileSize);
		fwrite(&lFileSize, sizeof(UINT), 1, pFile);

		fclose(pFile);

		bSuccess = TRUE;

		if( iSaveMode==PROJ_MODE_NORMAL ){
			g_bProjStylePaid = false;
			UpdateSVDVars();
			UpdateRecentProject( wstrProj );
			PostMessage(hNotifyWnd, MSG_OPERATE_COMPLETE, 0, 0);

			u_pProjLite = g_Undo.GetLastLite();
			ClearAutoProj();
		}
		else if( iSaveMode==PROJ_MODE_AUTO ){
			SetAutoSaveReg(true);
		}

		if( iSaveMode!=PROJ_MODE_UPLOAD ){
			u_pAutoLite = g_Undo.GetLastLite();
		}
	}

	if (SetEvent(g_hProjectEvent) == 0) {
		DWORD dwError = GetLastError();
		DebugPrint("Set Event error! err=%d", dwError);
	}

	DebugPrint("saving done\n");

	if( iSaveMode==PROJ_MODE_NORMAL ){
		if (bSuccess) {
			g_strProjectName = wstrProj;
			g_strLastProjSavePath = ExtractFilePath( g_strProjectName.c_str() ).c_str();
		}
		else{
			PostMessage(hNotifyWnd, MSG_OPERATE_FAILED, E_PROJ_FILENOTEXIST, 0);
		}
	}

	return bSuccess;
}

BOOL LoadProject(LPCSTR strProjectName, HWND hNotifyWnd) {
	DebugPrint("Opening project....");

	WaitForSingleObject(g_hProjectEvent, INFINITE);

	BOOL bSuccess = FALSE;
	int iError = E_PROJ_NOERROR;
	int iLoadMode = hNotifyWnd==NULL ? PROJ_MODE_AUTO : PROJ_MODE_NORMAL,

	// 全局变量清空
	g_bPredefine = false;
	g_bProjStylePaid = false;
	g_bMidiMelody = false;
	g_iMelodyKey = -1;
	g_fMusicVolume = 1;
	g_bComposeMute = false;
	g_iViewMode = 3;
	ClearGlobalVars();
	ClearStyleMap();

	FILE *pFile = NULL;
	if ((pFile = fopen(strProjectName, "rb")) != NULL) {
		DWORD dwProjectVersion;
		WORD wMajVersion, wMinVersion;
		UINT lFileSize = 0;
		fpos_t posBegin = 0;
		int	iContentView = 1;

		// 读取版本号
		fread(&dwProjectVersion, sizeof(DWORD), 1, pFile);
		if( LOWORD(dwProjectVersion)<2 ){
			wMajVersion = LOWORD(dwProjectVersion);
			wMinVersion = HIWORD(dwProjectVersion);
			dwProjectVersion = MAKELONG( wMinVersion, wMajVersion );
		}
		else{
			wMajVersion = HIWORD( dwProjectVersion );
			wMinVersion = LOWORD( dwProjectVersion );
		}

		// 读取文件长度
		fread(&lFileSize, sizeof(UINT), 1, pFile);
		// 检测文件长度
		fgetpos(pFile, &posBegin);
		fseek(pFile, 0, SEEK_END);
		if (lFileSize != ftell(pFile)) {
			iError = E_PROJ_FILECRUPT;
			goto STATEMENT_FALSE;
		}
		else {
			fsetpos(pFile, &posBegin);
		}

		if( wMajVersion<1 || wMajVersion==2 && wMinVersion>8
							 || wMajVersion==3 && wMinVersion>3
							 || wMajVersion==4 && wMinVersion>4 ){ //不可识别版本
			iError = E_PROJ_INVALIDVERSION;
			goto STATEMENT_FALSE;
		}
		else if( wMajVersion<2 ) { //不兼容1.0老版本
			iError = E_PROJ_EARLERVERSION;
			goto STATEMENT_FALSE;
		}
		else if( dwProjectVersion>g_dwProjectVersion ) { //后期版本
			iError = E_PROJ_LATERVERSION;
			goto STATEMENT_FALSE;
		}

		if( wMajVersion>5 || wMajVersion==5 && wMinVersion>=3 || wMajVersion==2 && wMinVersion>=7 )
			fread(&iLoadMode, sizeof(int), 1, pFile);

		if( wMajVersion==5 )
			iError = LoadVersion5( pFile, dwProjectVersion, hNotifyWnd, &iContentView );
		else if( wMajVersion==4 )
			iError = LoadVersion4( pFile, dwProjectVersion, hNotifyWnd );
		else if( wMajVersion==3 )
			iError = LoadVersion3( pFile, dwProjectVersion, hNotifyWnd );
		else if( wMajVersion==2 )
			iError = LoadVersion2( pFile, dwProjectVersion, hNotifyWnd, iLoadMode );

		long lPos = ftell( pFile );
		fclose( pFile );
		pFile = NULL;

		if (iError>E_PROJ_FATALERROR ) {
			goto STATEMENT_FALSE;
		}

		if( wMajVersion>=4 || wMajVersion==2 && wMinVersion>=6 ){
			int nCSSize = f_CS_LoadProject( strProjectName, lPos, dwProjectVersion );
			if( nCSSize<0 ){
				iError = E_PROJ_FILECRUPT;
				goto STATEMENT_FALSE;
			}

			lPos += nCSSize;
		}

		lFileSize = f_MM_LoadProject( iLoadMode, hNotifyWnd, strProjectName, lPos, dwProjectVersion );

		if( lFileSize<0 ){
			iError = E_PROJ_CANTLOADAUDIO;
			goto STATEMENT_FALSE;
		}

		g_bWeakup = g_Theme.IsWeadup();

		for( int i=g_aAudioTracks.size()-1; i>=0; i-- ){
			if( i<MAX_AUDIOTRACK && g_aAudioTracks[i]->lstBars.size()>0
									&& f_MM_AudioGetLength(i)>=0 ){
				if( wMajVersion>=5 ){ //获取音量信息
					for( int k=0; k<g_aAudioTracks[i]->lstBars.size(); k++ ){
						TWaveBar* pBar = g_aAudioTracks[i]->lstBars[k];

						for( int j=0; j<POINTS_PER_BAR; j++ ){
							pBar->aVols[j] = f_MM_GetAudioVolume( i, k + j/(double)POINTS_PER_BAR );
						}
					}
				}

				f_MM_SetStreamVolume( 0x10+i, g_aAudioTracks[i]->IsMute() ? 0
													: g_aAudioTracks[i]->volume / 100.0 );
			}
			else{
				DeleteAudioTrack( i, false );
                f_MM_AudioDeleteTrack( i );
			}
		}

		bSuccess = TRUE;

		if( hNotifyWnd )
			PostMessage(hNotifyWnd, MSG_OPERATE_COMPLETE, iError, 0);

		PostMessage( Application->MainFormHandle, UM_SETCONTENTVIEW, iContentView, 0 );
	}
	else {
		iError = E_PROJ_FILENOTEXIST;
	}

STATEMENT_FALSE:
	if( pFile ){
		fclose( pFile );
		pFile = NULL;
	}

	if (SetEvent(g_hProjectEvent) == 0) {
		DWORD dwError = GetLastError();
		DebugPrint("Set Event error! err=%d", dwError);
	}

	DebugPrint("opening done\n");

	if( iLoadMode!=PROJ_MODE_AUTO ) { //add by tj 2013/12/31
		if (!bSuccess) {
			PostMessage(hNotifyWnd, MSG_OPERATE_FAILED, iError, 0);
		}
		else {
			UpdateSVDVars();
			g_strProjectName = str2wstr( strProjectName );
			g_strLastProjSavePath = ExtractFilePath( g_strProjectName.c_str() ).c_str();
			UpdateRecentProject(g_strProjectName);
		}
	}

	return bSuccess;
}

TPROSTYLE* GetProjStyle( UINT idLoc, UINT idStyle, STYLELIST& aUnsolvedStyles )
{
	TPROSTYLE* pInfo = CheckStyle( idLoc, idStyle );

	if( !pInfo && idLoc!=0 && idLoc!=(UINT)-1 ){
		for( int t=0; t<aUnsolvedStyles.size(); t++ ){
			if( aUnsolvedStyles[t]->idLoc==idLoc
							&& aUnsolvedStyles[t]->idStyle==idStyle ){
				pInfo = aUnsolvedStyles[t];
				break;
			}
		}

		if( !pInfo ){
			pInfo = new TPROSTYLE;
			pInfo->idLoc = idLoc;
			pInfo->idStyle = idStyle;
			aUnsolvedStyles.push_back( pInfo );
		}
	}

	return pInfo;
}

int LoadOpusStages( TOpusStageList& lstStages, STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion )
{
	WORD wMajVersion = HIWORD( dwVersion ),
		wMinVersion = LOWORD( dwVersion );
	int num, nBars = 0;
	fread( &num, sizeof(int), 1, pFile );

	for( int i=0; i<num; i++ ){
		TOpusStage* pStage = new TOpusStage;

		fread( &pStage->iSegType, sizeof(char), 1, pFile );
		fread( &pStage->iSegNo, sizeof(char), 1, pFile );
		fread( &pStage->iSegKey, sizeof(char), 1, pFile );
		fread( &pStage->nVol, sizeof(char), 1, pFile );

		int count;
		fread( &count, sizeof(int), 1, pFile );
		for( int j=0; j<count; j++ ){
			TBar* pBar = new TBar;
			fread( &pBar->aChords, sizeof(TBarChords), 1, pFile );
			fread( &pBar->iBarKey, sizeof(char), 1, pFile );
			pStage->aBars.push_back( pBar );
		}
		nBars += count;

		fread( &count, sizeof(int), 1, pFile );
		for( int j=0; j<count; j++ ){
			TTrack * pTrack = new TTrack;

			fread( &pTrack->iStyleLoc, sizeof(UINT), 1, pFile );
			fread( &pTrack->iStyleId, sizeof(UINT), 1, pFile );
			fread( &pTrack->iSegNo, sizeof(BYTE), 1, pFile );
			fread( &pTrack->iChanNo, sizeof(BYTE), 1, pFile );
			fread( &pTrack->iChanSpec, sizeof(BYTE), 1, pFile );
			fread( &pTrack->iProg, sizeof(BYTE), 1, pFile );
			fread( &pTrack->iProgOrig, sizeof(BYTE), 1, pFile );
			fread( &pTrack->nVol, sizeof(BYTE), 1, pFile );
			fread( &pTrack->nVolOrig, sizeof(BYTE), 1, pFile );
			fread( &pTrack->iBank, sizeof(BYTE), 1, pFile );
			if( wMajVersion==5 && wMinVersion>=6 )
				fread( &pTrack->iFile, sizeof(BYTE), 1, pFile );

			TPROSTYLE* pTrackStyle = GetProjStyle( pTrack->iStyleLoc, pTrack->iStyleId, aUnsolvedStyles );
			if( !pTrackStyle ){ //无效的风格ID
				return E_PROJ_INVALIDSTYLE;
			}

			if( wMajVersion==5 && wMinVersion<4 ){
				if( pTrack->iBank!=0 )
					pTrack->nVol |= 0x80;

				pTrack->iBank = 0xFF;
			}

			pStage->aTracks.push_back( pTrack );
		}

		lstStages.push_back( pStage );
	}

	return nBars;
}

int LoadVersion5( FILE *pFile, DWORD dwVersion, HWND hNotifyWnd, int* iContentView )
{
	char strFont[MAX_PATH];
	string strStyleName;
	bool bUseful;
	int iError = E_PROJ_NOERROR;
	WORD wMinVersion = LOWORD( dwVersion );
	int nSize, iMelodyKey, iMelodyTimeSignature, nMelodyTempo;

	// 主要参数
	fread(&iMelodyTimeSignature, sizeof(int), 1, pFile);
	fread(&nMelodyTempo, sizeof(int), 1, pFile);
	fread(&iMelodyKey, sizeof(int), 1, pFile);

	if( g_iMelodyTimeSignature!=iMelodyTimeSignature ){
		SetMelodyTS(iMelodyTimeSignature);
		SelectStyle();
		PostMessage( Application->MainFormHandle, UM_CHANGETT, true, -1 );
	}

	SetMelodyTempo(nMelodyTempo);
	g_iMelodyKey = iMelodyKey;

	// 读取音色库文件名
	fread(&nSize, sizeof(int), 1, pFile);

	if (nSize > 0) {
		fread(strFont, sizeof(char), nSize, pFile);
		strcpy( g_strSoundFont, strFont );
	}

	if( wMinVersion>=5 )
		fread( &g_bExtFont, sizeof(bool), 1, pFile );

	// 各项音量设值
	fread(&g_fRecordVolume, sizeof(float), 1, pFile);
	if( g_fRecordVolume>1 ) g_fRecordVolume = 1;
	if( g_fRecordVolume<0 ) g_fRecordVolume = 0;

	fread(&g_fSpeakerVolume, sizeof(float), 1, pFile);
	if( g_fSpeakerVolume>1 )  g_fSpeakerVolume= 1;
	if( g_fSpeakerVolume<0 )  g_fSpeakerVolume= 0;

	fread(&g_fMusicVolume, sizeof(float), 1, pFile);
	if( g_fMusicVolume>1 ) g_fMusicVolume = 1;
	if( g_fMusicVolume<0 ) g_fMusicVolume = 0;

	int iMute;
	fread(&iMute, sizeof(int), 1, pFile);
	g_bComposeMute = iMute!=0;

	f_MM_SetStreamVolume( 0, g_fSpeakerVolume );
	f_MM_SetStreamVolume( 1, g_fRecordVolume );
	f_MM_SetStreamVolume( 4, g_bComposeMute ? 0 : g_fMusicVolume );

	STYLELIST aUnsolvedStyles;

	iError = g_Theme.ReadProj( aUnsolvedStyles, pFile, dwVersion );
	if( iError!=E_PROJ_NOERROR )
		return iError;

	iError = g_Opus.ReadProj( aUnsolvedStyles, pFile, dwVersion );
	if( iError!=E_PROJ_NOERROR )
		return iError;

	if( wMinVersion>=6 ){
		iError = g_Midi.ReadProj( pFile, dwVersion );
		if( iError!=E_PROJ_NOERROR )
			return iError;
	}

	if( wMinVersion>=4 ){
		//使用的音源
		bool bReset = false;
		BANKMAPLIST lstBank;
		int nCount;

		fread(&nCount, sizeof(int), 1, pFile);
		for( int i=0; i<nCount; i++ ){
			BYTE len;
			BYTE iBankNew = 0xFF;

			TBankMap* pMap = new TBankMap;
			fread(&pMap->iBankOld, sizeof(BYTE), 1, pFile);

			if( pMap->iBankOld<0x80 ){
				fread(&len, sizeof(BYTE), 1, pFile);
				fread(strFont, sizeof(char), len, pFile);
				strFont[len] = '\0';
				for( int j=0; j<g_lstFonts.size(); j++ ){
					if( !strcmp( g_lstFonts[j]->strFontName, strFont ) ){
						iBankNew = j;
						break;
					}
				}
			}
			else{
				DWORD uniqueID = 0;
				fread( &uniqueID, sizeof(DWORD), 1, pFile );

				BYTE cmprMem[100000];
				int lenMem = 100000;
				fread( &lenMem, sizeof(int), 1, pFile );

				if( lenMem>0 )
					fread( cmprMem, 1, lenMem, pFile );

				for( int j=0; j<g_lstVSTi.size(); j++ ){
					if( uniqueID==g_lstVSTi[j]->uniqueID ){
						if( f_MM_LoadVSTi( j+0x80, g_lstVSTi[j]->strFileName )==S_OK ){
							iBankNew = j + 0x80;

							f_MM_HandleVSTiPreset( iBankNew, lenMem, cmprMem, true );
						}

						break;
					}
				}
			}

			pMap->iBankNew = iBankNew;
			lstBank.push_back( pMap );

			if( pMap->iBankOld!=pMap->iBankNew )
				bReset = true;

			if( iBankNew==0xFF )
				iError |= E_PROJ_INVALIDFONT;
		}

		if( bReset ){
			g_Theme.SetSpecBanks( lstBank );
			g_Opus.SetSpecBanks( lstBank );
			//g_Midi.SetSpecBanks( lstBank );
			g_Midi.ClearMidiTracks();
		}
	}

	g_Midi.SortMidiTracks();

	iError |= g_Audio.ReadProj( pFile, dwVersion );
	if( iError > E_PROJ_FATALERROR )
		return iError;

	//PreStylePanel
//	bool bAuthority = g_bLogon && (g_infoUser.accountInfo.authority & 0x1000);

	UINT idPreLoc, idPreStyle;
	fread( &idPreLoc, sizeof(UINT), 1, pFile );
	fread( &idPreStyle, sizeof(UINT), 1, pFile );

	TPROSTYLE* info = CheckStyle( idPreLoc, idPreStyle );//GetProjStyle( idPreLoc, idPreStyle, aUnsolvedStyles );
	TStyleItem* pSty = new TStyleItem( info, OPT_FONTPROG | OPT_SAVE );

	int num;
	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		char st, sn, vol;
		int bars;

		fread( &st, sizeof(char), 1, pFile );
		fread( &sn, sizeof(char), 1, pFile );
		fread( &vol, sizeof(char), 1, pFile );
		fread( &bars, sizeof(int), 1, pFile );

		DWORD opts = OPT_DEL | OPT_VOL | (st<SEGTYPE_INTRO ? OPT_BRUSH : 0);
		TSegmentItem* pSeg = pSty->AddSegment( st, sn, opts, 0, -1, vol );
		pSeg->nBars = bars;

		int count;
//		TTrackItem* pTrkPrev = NULL;
		fread( &count, sizeof(int), 1, pFile );
		for( int j=0; j<count; j++ ){
			UINT idItemLoc, idItemStyle;
//			TTrackItem* pTrk = new TTrackItem;

			fread( &idItemLoc, sizeof(UINT), 1, pFile );
			fread( &idItemStyle, sizeof(UINT), 1, pFile );

			if( wMinVersion<6 ){
				char iSegType;
				fread( &iSegType, sizeof(char), 1, pFile );
            }

			TTrack* pTrk = new TTrack;
			fread( &pTrk->iSegNo, sizeof(char), 1, pFile );
			fread( &pTrk->iChanNo, sizeof(char), 1, pFile );
			fread( &pTrk->iChanSpec, sizeof(char), 1, pFile );
			fread( &pTrk->iProg, sizeof(char), 1, pFile );
			fread( &pTrk->iProgOrig, sizeof(char), 1, pFile );
			fread( &pTrk->nVol, sizeof(char), 1, pFile );
			fread( &pTrk->nVolOrig, sizeof(char), 1, pFile );

			if( wMinVersion<4 ){
				bool bMute = false;
				fread( &bMute, sizeof(bool), 1, pFile );

				if( bMute )
					pTrk->nVol |= 0x80;
			}

			TPROSTYLE* pInfo = CheckStyle( idItemLoc, idItemStyle );//GetProjStyle( idItemLoc, idItemStyle, aUnsolvedStyles );

			if( !pInfo ){
				delete pTrk;
				continue;
			}

			DWORD dwTrkOpt = OPT_DEL|OPT_FONTPROG|OPT_VOL;
			if( pSeg->iSegType<=SEGTYPE_FILL )
				dwTrkOpt |= OPT_TEXTURE;

			pTrk->iStyleLoc = idItemLoc;
			pTrk->iStyleId = idItemStyle;
			pSeg->AddTrack( pInfo, pTrk, dwTrkOpt, true );
		}

		if( pSeg->aItems->Count==0 ){
			pSty->DeleteSegment( pSeg );
		}
		else if( !pSty->pStyle ){
			pSty->pStyle = ((TTrackItem*)pSeg->aItems->Items[0])->pStyle;
		}
	}

	if( pSty->pStyle && pSty->aItems->Count>0 ){
		g_pPreStyle = pSty;
	}
	else
		delete pSty;

	//段落预设
	fread( &g_iPreStage, sizeof(int), 1, pFile );
	//视图模式
	fread( iContentView, sizeof(int), 1, pFile );
	//预设工程
	fread( &g_bPredefine, sizeof(bool), 1, pFile );
	//MIDI输入工程
	fread( &g_bMidiMelody, sizeof(bool), 1, pFile );

	//本地风格数据
	BYTE* mem = new BYTE[1000000];

	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		UINT idLoc, idStyle;
		int len;

		fread( &idLoc, sizeof(UINT), 1, pFile );
		fread( &idStyle, sizeof(UINT), 1, pFile );
		fread( &len, sizeof(int), 1, pFile );
		if( len>0 ){
			fread( mem, 1, len, pFile );

			for( int j=0; j<aUnsolvedStyles.size(); j++ ){
				TPROSTYLE* pInfo = aUnsolvedStyles[j];
				if( idLoc==pInfo->idLoc && idStyle==pInfo->idStyle ){
					int id = f_CM_ProjRestoreStyle( len, mem );

					if( id>0 ){
						g_Theme.SetTempStyle( idLoc, idStyle, id );
						g_Opus.SetTempStyle( idLoc, idStyle, id );

						TTempStyleMap* pMap = new TTempStyleMap;
						pMap->idTemp = id;
						pMap->idLoc = pInfo->idLoc;
						pMap->idStyle = pInfo->idStyle;
						u_aTempStyleMap.push_back( pMap );

						pInfo->idLoc = -1;
						pInfo->idStyle = id;
						g_aTempStyles.push_back( pInfo );

						aUnsolvedStyles.erase( aUnsolvedStyles.begin() + j );
					}

					break;
				}
			}
		}
	}

	delete[] mem;

	if( !aUnsolvedStyles.empty() ){
		for( int i=0; i<aUnsolvedStyles.size(); i++ ){
			delete aUnsolvedStyles[i];
		}
		aUnsolvedStyles.clear();

		return E_PROJ_INVALIDSTYLE;
	}

	g_Opus.BuildStyleItem();

	return iError;
}

int LoadVersion4( FILE *pFile, DWORD dwVersion, HWND hNotifyWnd )
{
	char strFont[MAX_PATH];
	string strStyleName;
	bool bUseful;
	int iError = E_PROJ_NOERROR;
	WORD wMinVersion = LOWORD( dwVersion );
	int nSize, iMelodyKey, iMelodyTimeSignature, nMelodyTempo;

	// 主要参数
	fread(&iMelodyTimeSignature, sizeof(int), 1, pFile);
	fread(&nMelodyTempo, sizeof(int), 1, pFile);
	fread(&iMelodyKey, sizeof(int), 1, pFile);

	if( g_iMelodyTimeSignature!=iMelodyTimeSignature ){
		SetMelodyTS(iMelodyTimeSignature);
		SelectStyle();
		PostMessage( Application->MainFormHandle, UM_CHANGETT, true, -1 );
	}

	SetMelodyTempo(nMelodyTempo);
	g_iMelodyKey = iMelodyKey;

	// 读取音色库文件名
	fread(&nSize, sizeof(int), 1, pFile);

	if (nSize > 0) {
		fread(strFont, sizeof(char), nSize, pFile);
		strcpy( g_strSoundFont, strFont );
	}

	// 各项音量设值
	fread(&g_fRecordVolume, sizeof(float), 1, pFile);
	if( g_fRecordVolume>1 ) g_fRecordVolume = 1;
	if( g_fRecordVolume<0 ) g_fRecordVolume = 0;

	fread(&g_fSpeakerVolume, sizeof(float), 1, pFile);
	if( g_fSpeakerVolume>1 )  g_fSpeakerVolume= 1;
	if( g_fSpeakerVolume<0 )  g_fSpeakerVolume= 0;

	float fAudioVolume = 1;
	fread(&fAudioVolume, sizeof(float), 1, pFile);
	if( fAudioVolume>1 ) fAudioVolume = 1;
	if( fAudioVolume<0 ) fAudioVolume = 0;

	fread(&g_fMusicVolume, sizeof(float), 1, pFile);
	if( g_fMusicVolume>1 ) g_fMusicVolume = 1;
	if( g_fMusicVolume<0 ) g_fMusicVolume = 0;

	f_MM_SetStreamVolume( 0, g_fSpeakerVolume );
	f_MM_SetStreamVolume( 1, g_fRecordVolume );
	f_MM_SetStreamVolume( 4, g_fMusicVolume );

	TBarList lstBars;
	vector<int> lstStages;
	// g_lstRawBars
	int num;
	fread( &num, sizeof(int), 1, pFile );

	if( num>0 ){
		for( int i=0; i<num; i++ ){
			TWaveBar* pWvBar = new TWaveBar;
			fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );

			g_aAudioTracks[0]->lstBars.push_back( pWvBar );

			TBar* pBar = new TBar;
			fread( &pBar->aChords, sizeof(TBarChords), 1, pFile );

			if( HIWORD( dwVersion )>4 || wMinVersion>=3 )
				fread( &pBar->iBarKey, sizeof(char), 1, pFile );
			else
				pBar->iBarKey = iMelodyKey;

			lstBars.push_back( pBar );
		}

		AudioEffectsDefault( 0, false );
		g_aAudioTracks[0]->volume = (int)(fAudioVolume * 100);
	}

	// g_lstRawStages
	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		int iRaw = 0;
		fread( &iRaw, sizeof(int), 1, pFile );
		lstStages.push_back( iRaw );
	}

	// g_lstOpusStages
	TAudioTrack* pAudioTrack = NULL;

	fread( &num, sizeof(int), 1, pFile );
	if( num>0 ){
		pAudioTrack = new TAudioTrack;
		pAudioTrack->volume = (int)(fAudioVolume * 100);
		g_aAudioTracks.push_back( pAudioTrack );
		g_aAudioTracks[0]->Hide();// = true;

		for( int i=0; i<num; i++ ){
			TOpusStage* pStage = new TOpusStage;

			if( HIWORD( dwVersion )==4 && wMinVersion<3 ){
				int iSegType, iSegNo;
				fread( &iSegType, sizeof(int), 1, pFile );
				fread( &iSegNo, sizeof(int), 1, pFile );

				pStage->iSegType = iSegType;
				pStage->iSegNo = iSegNo;
				pStage->iSegKey = iMelodyKey;
			}
			else{
				fread( &pStage->iSegType, sizeof(char), 1, pFile );
				fread( &pStage->iSegNo, sizeof(char), 1, pFile );
				fread( &pStage->iSegKey, sizeof(char), 1, pFile );
			}

			int count;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				TWaveBar* pWvBar = new TWaveBar;
				fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );
				pAudioTrack->lstBars.push_back( pWvBar );

				TBar* pBar = new TBar;
				fread( &pBar->aChords, sizeof(TBarChords), 1, pFile );

				if( HIWORD( dwVersion )>4 || wMinVersion>=3 )
					fread( &pBar->iBarKey, sizeof(char), 1, pFile );
				else
					pBar->iBarKey = iMelodyKey;

				pStage->aBars.push_back( pBar );
			}

			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				TTrackOldProj track;
				fread( &track, sizeof(TTrackOldProj), 1, pFile );

				if( track.iStyleLoc==0 ){
					TPROSTYLE* pTrackStyle = CheckStyle( track.iStyleLoc, track.iStyleId );
					if( !pTrackStyle ){ //无效的风格
						delete pStage;
						return E_PROJ_INVALIDSTYLE;
					}
				}

				TTrack* pTrk = new TTrack;
				pTrk->iStyleLoc = track.iStyleLoc;
				pTrk->iStyleId = track.iStyleId;
				pTrk->iSegNo = track.iSegNo;
				pTrk->iChanNo = track.iChanNo;
				pTrk->iChanSpec = track.iChanSpec;
				pTrk->iProg = track.iProg;
				pTrk->nVol = track.nVol;

				pStage->aTracks.push_back( pTrk );
			}

			g_lstOpusStages.push_back( pStage );
		}

		g_Opus.CountBars();
	}

	//g_aAudioEffects
	for( int i=0; i<MAX_FX_NUM; i++ ){
		int count;
		fread(&count, sizeof(int), 1, pFile);

		for( int j=0; j<count; j++ ){
			TEffect pAE;
			fread( &pAE.iBarStart, sizeof(int), 1, pFile );
			fread( &pAE.iPointStart, sizeof(int), 1, pFile );
			fread( &pAE.iBarEnd, sizeof(int), 1, pFile );
			fread( &pAE.iPointEnd, sizeof(int), 1, pFile );
			fread( &pAE.iPreset, sizeof(int), 1, pFile );
			fread( &pAE.bOn, sizeof(bool), 1, pFile );
			if( pAE.bOn ){
				pAE.aParams = new float[6];
				fread( pAE.aParams, sizeof(float), 6, pFile );
			}

			if( pAE.iBarStart==0 && pAE.iBarEnd>=pAudioTrack->lstBars.size()-1 ){
				int iType = g_aAudioEffectTypes[i];

				if( iType!=FX_PITCH ){
					int nSize = GetFxParamNum( iType );
					float* pParams = new float[nSize];
					int iPreset = pAE.iPreset;

					int nPresetCount = GetFxPresetCount( iType );

					if( pAE.bOn )
						memcpy( pParams, pAE.aParams, sizeof(float)*nSize );
					else{
						if( iPreset>=nPresetCount )
							iPreset = 0;

						GetFxPreset( iType, iPreset, pParams );
					}

					TAudioFx* pFx = new TAudioFx( iType, iPreset, pParams, nSize, !pAE.bOn );
					pAudioTrack->lstFxs.push_back( pFx );
				}
			}
			else{
				iError |= E_PROJ_INVALIDFX;
            }
		}
	}

	//AudStylePanel信息
	//PreStylePanel/UseStylePanel信息
	bool bAuthority = g_bLogon && (g_infoUser.accountInfo.authority & 0x1000),
		bNoAuthority = false,
		bInvalid = false;
	STYLELIST aUnsolvedStyles;
	TStyleItem *pPreStyle = NULL,
			   *pUseStyle = NULL;

	for( int n=0; n<2; n++ ){
		TStyleItem*& pSty = n==0 ? pPreStyle : pUseStyle;
		pSty = new TStyleItem;

		UINT idStyItemLoc, idStyItemStyle;
		fread( &idStyItemLoc, sizeof(UINT), 1, pFile );
		fread( &idStyItemStyle, sizeof(UINT), 1, pFile );
		fread( &pSty->iType, sizeof(char), 1, pFile );
		fread( &pSty->nBars, sizeof(int), 1, pFile );

		int nSegNum[4];
		fread( nSegNum, sizeof(int), 4, pFile );
		for( int i=0; i<4; i++ ){
			pSty->nSegNum[i] = nSegNum[i];
		}

		DWORD iOpt;
		fread( &num, sizeof(int), 1, pFile );
		for( int i=0; i<num; i++ ){
			fread( &iOpt, sizeof(DWORD), 1, pFile );
		}

		TOpusStage* pStage = NULL;
		TSegmentItem* pSegPrev = NULL;
		fread( &num, sizeof(int), 1, pFile );
		for( int i=0; i<num; i++ ){
			TSegmentItem* pSeg = new TSegmentItem;
			pSeg->bAutoSpec = n==0;

			fread( &pSeg->iType, sizeof(char), 1, pFile );
			fread( &pSeg->iSegType, sizeof(char), 1, pFile );
			fread( &pSeg->iSegNo, sizeof(char), 1, pFile );
			fread( &pSeg->iInd, sizeof(char), 1, pFile );
			fread( &pSeg->volume, sizeof(char), 1, pFile );
			fread( &pSeg->nBars, sizeof(int), 1, pFile );
			fread( pSeg->aChanUsed, sizeof(bool), 16, pFile );

			int count;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				fread( &iOpt, sizeof(DWORD), 1, pFile );
			}

			if( n>0 ){
				pStage = g_lstOpusStages[i];
				pStage->nVol = pSeg->volume;
			}

			TTrackItem* pTrkPrev = NULL;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				int idItemLoc, idItemStyle;

				TTrackItem* pTrk = new TTrackItem;
				TTrack* pTrack = new TTrack;

				fread( &pTrk->iType, sizeof(char), 1, pFile );
				fread( &idItemLoc, sizeof(UINT), 1, pFile );
				fread( &idItemStyle, sizeof(UINT), 1, pFile );

				char iSegType;
				fread( &iSegType, sizeof(char), 1, pFile );
	//			fread( &pTrk->iSegType, sizeof(char), 1, pFile );
				fread( &pTrack->iSegNo, sizeof(char), 1, pFile );
				fread( &pTrack->iChanNo, sizeof(char), 1, pFile );
				fread( &pTrack->iChanSpec, sizeof(char), 1, pFile );
				fread( &pTrack->iProg, sizeof(char), 1, pFile );
				fread( &pTrack->iProgOrig, sizeof(char), 1, pFile );
				fread( &pTrack->nVol, sizeof(char), 1, pFile );
				fread( &pTrack->nVolOrig, sizeof(char), 1, pFile );

				bool bMute = false;
				fread( &bMute, sizeof(bool), 1, pFile );
				if( bMute )
					pTrack->nVol |= 0x80;

				int cn;
				fread( &cn, sizeof(int), 1, pFile );
				for( int k=0; k<cn; k++ ){
					fread( &iOpt, sizeof(DWORD), 1, pFile );
				}

				TPROSTYLE* pInfo = NULL;
				if( bAuthority || idItemLoc==0 )
					pInfo = CheckStyle( idItemLoc, idItemStyle );

				if( !pInfo ){
					if( n==0 ){
						delete pTrk;
						delete pTrack;
						continue;
					}

					if( idItemLoc!=0 && idItemLoc!=(UINT)-1 ){
						for( int t=0; t<aUnsolvedStyles.size(); t++ ){
							if( aUnsolvedStyles[t]->idLoc==idItemLoc
											&& aUnsolvedStyles[t]->idStyle==idItemStyle ){
								pInfo = aUnsolvedStyles[t];
								break;
							}
						}

						if( !pInfo ){
							pInfo = new TPROSTYLE;
							pInfo->idLoc = idItemLoc;
							pInfo->idStyle = idItemStyle;
							aUnsolvedStyles.push_back( pInfo );
						}
					}
					else{
						bInvalid = true;

						delete pTrk;
						delete pTrack;
						delete pSeg;

						goto STYLE_CHECK_OVER;
					}
				}

				pTrk->pStyle = pInfo;
				pTrack->iStyleLoc = pInfo->idLoc;
				pTrack->iStyleId = pInfo->idStyle;

				pTrk->aOptions->Add( (void*)OPT_DEL );
				pTrk->aOptions->Add( (void*)OPT_VOL );

				if( pSeg->iSegType<=SEGTYPE_FILL )
					pTrk->aOptions->Add( (void*)OPT_TEXTURE );

				if( n==0 ){
					pTrk->aOptions->Add( (void*)OPT_FONTPROG );
					pTrk->pTrack = pTrack;
					pTrk->bOwnTrack = true;
				}
				else if( pStage ){
					TTrack* pTrackSet = pStage->aTracks[j];
					pTrackSet->iProgOrig = pTrack->iProg;
					pTrackSet->nVolOrig = pTrack->nVolOrig;
					pTrackSet->nVol = pTrack->nVol;

					pTrk->pTrack = pTrackSet;
					delete pTrack;
				}

				pTrk->up = pSeg;
				if( pTrkPrev ){
					pTrk->prev = pTrkPrev;
					pTrkPrev->next = pTrk;
				}
				pTrkPrev = pTrk;

				pSeg->aItems->Add( pTrk );
			}

			if( pSeg->aItems->Count>0 || n>0 ){
				pSeg->aOptions->Add( (void*)OPT_DEL );
				pSeg->aOptions->Add( (void*)OPT_VOL );
				if( pSeg->iType<SEGTYPE_INTRO )
					pSeg->aOptions->Add( (void*)OPT_BRUSH );

				pSeg->up = pSty;
				if( pSegPrev ){
					pSeg->prev = pSegPrev;
					pSegPrev->next = pSeg;
				}
				pSegPrev = pSeg;

				pSty->aItems->Add( pSeg );
			}
			else{
				delete pSeg;
			}
		}

		TPROSTYLE* info = NULL;
		if( bAuthority || idStyItemLoc==0 || idStyItemLoc==1 )
			info = CheckStyle( idStyItemLoc, idStyItemStyle );

		if( !info ){
			if( n==1 && idStyItemLoc!=0 && idStyItemLoc!=1 && idStyItemLoc!=(UINT)-1 ){
				for( int t=0; t<aUnsolvedStyles.size(); t++ ){
					if( aUnsolvedStyles[t]->idLoc==idStyItemLoc
									&& aUnsolvedStyles[t]->idStyle==idStyItemStyle ){
						info = aUnsolvedStyles[t];
						break;
					}
				}

				if( !info ){
					info = new TPROSTYLE;
					info->idLoc = idStyItemLoc;
					info->idStyle = idStyItemStyle;
					aUnsolvedStyles.push_back( info );
				}
			}

			if( !info && pSty->aItems->Count>0 ){
				for( int i=0; i<pSty->aItems->Count; i++ ){
					TSegmentItem* pSeg = (TSegmentItem*)pSty->aItems->Items[i];

					if( pSeg->aItems->Count>0 ){
						info = ((TTrackItem*)pSeg->aItems->Items[0])->pStyle;
						break;
					}
				}
			}
		}

		if( info && ( pSty->aItems->Count>0 || n>0 ) ){
			pSty->pStyle = info;

			if( n==0 ){
				pSty->aOptions->Add((void*)OPT_FONTPROG);
				pSty->aOptions->Add((void*)OPT_SAVE);
			}
		}
		else{
			delete pSty;
			pSty = NULL;

			if( n>0 ){
				bInvalid = true;
				goto STYLE_CHECK_OVER;
			}
		}
	}

STYLE_CHECK_OVER:
	if( bInvalid ){
		if( pPreStyle ){
			delete pPreStyle;
		}

		if( pUseStyle ){
			delete pUseStyle;
		}

		return E_PROJ_INVALIDSTYLE;
	}
	else{
		g_pPreStyle = pPreStyle;
		g_pUseStyle = pUseStyle;
	}

	//段落预设
	fread( &g_iPreStage, sizeof(int), 1, pFile );
	//视图模式
	int iViewMode;
	fread( &iViewMode, sizeof(int), 1, pFile );
	//预设工程
	fread( &g_bPredefine, sizeof(bool), 1, pFile );
	//MIDI输入工程
	if( HIWORD( dwVersion )>4 || wMinVersion>=4 )
		fread( &g_bMidiMelody, sizeof(bool), 1, pFile );

	//本地风格数据
	BYTE* mem = new BYTE[1000000];

	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		UINT idLoc, idStyle;
		int len;

		fread( &idLoc, sizeof(UINT), 1, pFile );
		fread( &idStyle, sizeof(UINT), 1, pFile );
		fread( &len, sizeof(int), 1, pFile );
		if( len>0 ){
			fread( mem, 1, len, pFile );

			for( int j=0; j<aUnsolvedStyles.size(); j++ ){
				TPROSTYLE* pInfo = aUnsolvedStyles[j];
				if( idLoc==pInfo->idLoc && idStyle==pInfo->idStyle ){
					int id = f_CM_ProjRestoreStyle( len, mem );

					if( id>0 ){
						for( int s=0; s<g_lstOpusStages.size(); s++ ){
							TOpusStage* pStage = g_lstOpusStages[s];
							for( int t=0; t<pStage->aTracks.size(); t++ ){
								TTrack* pTrack = pStage->aTracks[t];
								if( pTrack->iStyleLoc==idLoc && pTrack->iStyleId==idStyle ){
									pTrack->iStyleLoc = -1;
									pTrack->iStyleId = id;
								}
							}
						}

						TTempStyleMap* pMap = new TTempStyleMap;
						pMap->idTemp = id;
						pMap->idLoc = pInfo->idLoc;
						pMap->idStyle = pInfo->idStyle;
						u_aTempStyleMap.push_back( pMap );

						pInfo->idLoc = -1;
						pInfo->idStyle = id;
						g_aTempStyles.push_back( pInfo );

						aUnsolvedStyles.erase( aUnsolvedStyles.begin() + j );
					}

					break;
				}
			}
		}
	}

	delete[] mem;

	if( !aUnsolvedStyles.empty() ){
		for( int i=0; i<aUnsolvedStyles.size(); i++ ){
			delete aUnsolvedStyles[i];
		}
		aUnsolvedStyles.clear();

		return E_PROJ_INVALIDSTYLE;
	}

	g_Theme.Build( lstBars, lstStages );

	return iError;
}

int LoadVersion3( FILE *pFile, DWORD dwVersion, HWND hNotifyWnd )
{
	char strFont[MAX_PATH];
	string strStyleName;
	bool bUseful;
	int iError = E_PROJ_NOERROR;
	WORD wMinVersion = LOWORD( dwVersion );
	int nSize, iMelodyKey, iMelodyTimeSignature, nMelodyTempo;

	// 主要参数
	UINT idStyle = 0;
	fread(&idStyle, sizeof(UINT), 1, pFile);
	fread(&iMelodyTimeSignature, sizeof(int), 1, pFile);
	fread(&nMelodyTempo, sizeof(int), 1, pFile);
	fread(&iMelodyKey, sizeof(int), 1, pFile);

	if( g_iMelodyTimeSignature!=iMelodyTimeSignature ){
		SetMelodyTS(iMelodyTimeSignature);
		SelectStyle();
		PostMessage( Application->MainFormHandle, UM_CHANGETT, true, -1 );
	}

	TPROSTYLE* pStyle = CheckStyle( 0, idStyle );
	if( !pStyle )
		return E_PROJ_INVALIDSTYLE;

	SetMelodyTempo(nMelodyTempo);
	g_iMelodyKey = iMelodyKey;

	// 读取音色库文件名
	fread(&nSize, sizeof(int), 1, pFile);

	if (nSize > 0) {
		fread(strFont, sizeof(char), nSize, pFile);
		strcpy( g_strSoundFont, strFont );
	}

	// 各项音量设值
	fread(&g_fRecordVolume, sizeof(float), 1, pFile);
	if( g_fRecordVolume>1 ) g_fRecordVolume = 1;
	if( g_fRecordVolume<0 ) g_fRecordVolume = 0;

	fread(&g_fSpeakerVolume, sizeof(float), 1, pFile);
	if( g_fSpeakerVolume>1 )  g_fSpeakerVolume= 1;
	if( g_fSpeakerVolume<0 )  g_fSpeakerVolume= 0;

	float fAudioVolume = 1;
	fread(&fAudioVolume, sizeof(float), 1, pFile);
	if( fAudioVolume>1 ) fAudioVolume = 1;
	if( fAudioVolume<0 ) fAudioVolume = 0;

	fread(&g_fMusicVolume, sizeof(float), 1, pFile);
	if( g_fMusicVolume>1 ) g_fMusicVolume = 1;
	if( g_fMusicVolume<0 ) g_fMusicVolume = 0;

	f_MM_SetStreamVolume( 0, g_fSpeakerVolume );
	f_MM_SetStreamVolume( 1, g_fRecordVolume );
	f_MM_SetStreamVolume( 4, g_fMusicVolume );

	// g_lstRawBars
	TBarList lstBars;
	int num;
	fread( &num, sizeof(int), 1, pFile );

	if( num>0 ){
		for( int i=0; i<num; i++ ){
			TWaveBar* pWvBar = new TWaveBar;
			fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );
			g_aAudioTracks[0]->lstBars.push_back( pWvBar );

			TBar* pBar = new TBar;
			fread( &pBar->aChords, sizeof(TBarChords), 1, pFile );

			pBar->iBarKey = iMelodyKey;
			lstBars.push_back( pBar );
		}

		AudioEffectsDefault( 0, false );
		g_aAudioTracks[0]->volume = (int)(fAudioVolume * 100);
	}

	// g_lstRawStages
	vector<int> lstStages;
	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		int iRaw = 0;
		fread( &iRaw, sizeof(int), 1, pFile );
		lstStages.push_back( iRaw );
	}

	// g_lstOpusStages
	TAudioTrack* pAudioTrack = NULL;

	fread( &num, sizeof(int), 1, pFile );
	if( num>0 ){
		pAudioTrack = new TAudioTrack;
		pAudioTrack->volume = (int)(fAudioVolume * 100);
		g_aAudioTracks.push_back( pAudioTrack );
		g_aAudioTracks[0]->Hide();// = true;

		for( int i=0; i<num; i++ ){
			TOpusStage* pStage = new TOpusStage;
			int idStageStyle, iSegType, iSegNo;

			fread( &idStageStyle, sizeof(UINT), 1, pFile );
			fread( &iSegType, sizeof(int), 1, pFile );
			fread( &iSegNo, sizeof(int), 1, pFile );

			pStage->iSegType = iSegType;
			pStage->iSegNo = iSegNo;
			pStage->iSegKey = iMelodyKey;

			if( pStage->iSegType>=SEGTYPE_INTRO ){
				if( pStage->iSegNo % 2 )
					pStage->iSegNo = pStage->iSegNo/2 + 4;
				else
					pStage->iSegNo /= 2;
			}

			int count;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				TWaveBar* pWvBar = new TWaveBar;
				fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );
				pAudioTrack->lstBars.push_back( pWvBar );

				TBar* pBar = new TBar;
				fread( &pBar->aChords, sizeof(TBarChords), 1, pFile );

				pBar->iBarKey = iMelodyKey;
				pStage->aBars.push_back( pBar );
			}

			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				TTrackOld trkOld;
				fread( &trkOld, sizeof(TTrackOld), 1, pFile );

				TPROSTYLE* pTrackStyle = CheckStyle( 0, trkOld.iStyleId );
				if( !pTrackStyle ){
					delete pStage;
					return E_PROJ_INVALIDSTYLE;
				}

				TTrack * pTrack = new TTrack;
				pTrack->iStyleId = trkOld.iStyleId;
				pTrack->iStyleLoc = trkOld.iStyleLoc;
				pTrack->iSegNo = trkOld.iSegNo;
				if( pStage->iSegType>=SEGTYPE_INTRO ){
					if( pTrack->iSegNo % 2 )
						pTrack->iSegNo = pTrack->iSegNo/2 + 4;
					else
						pTrack->iSegNo /= 2;
				}
				pTrack->iChanNo = trkOld.iChanNo;
				pTrack->iChanSpec = trkOld.iChanSpec;
				pTrack->iProg = trkOld.iProg;
				pTrack->nVol = trkOld.nVol;

				pStage->aTracks.push_back( pTrack );
			}

			g_lstOpusStages.push_back( pStage );
		}

		g_Opus.CountBars();
	}

	//g_aAudioEffects
	for( int i=0; i<MAX_FX_NUM; i++ ){
		int count;
		fread(&count, sizeof(int), 1, pFile);

		for( int j=0; j<count; j++ ){
			TEffect pAE;
			fread( &pAE.iBarStart, sizeof(int), 1, pFile );
			fread( &pAE.iPointStart, sizeof(int), 1, pFile );
			fread( &pAE.iBarEnd, sizeof(int), 1, pFile );
			fread( &pAE.iPointEnd, sizeof(int), 1, pFile );
			fread( &pAE.iPreset, sizeof(int), 1, pFile );
			fread( &pAE.bOn, sizeof(bool), 1, pFile );
			if( pAE.bOn ){
				pAE.aParams = new float[6];
				fread( pAE.aParams, sizeof(float), 6, pFile );
			}

			if( pAE.iBarStart==0 && pAE.iBarEnd>=pAudioTrack->lstBars.size()-1 ){
				int iType = g_aAudioEffectTypes[i];

				if( iType!=FX_PITCH ){
					int nSize = GetFxParamNum( iType );
					float* pParams = new float[nSize];
					int iPreset = pAE.iPreset;

					int nPresetCount = GetFxPresetCount( iType );

					if( pAE.bOn )
						memcpy( pParams, pAE.aParams, sizeof(float)*nSize );
					else{
						if( iPreset>=nPresetCount )
							iPreset = 0;

						GetFxPreset( iType, iPreset, pParams );
					}

					TAudioFx* pFx = new TAudioFx( iType, iPreset, pParams, nSize, !pAE.bOn );
					pAudioTrack->lstFxs.push_back( pFx );
				}
			}
			else{
				iError |= E_PROJ_INVALIDFX;
            }
		}
	}

	//AudStylePanel信息
	//PreStylePanel/UseStylePanel信息
	TStyleItem *pPreStyle = NULL,
			   *pUseStyle = NULL;
	bool bInvalid = false;

	for( int n=0; n<2; n++ ){
		int idStyItemStyle;
		TStyleItem*& pSty = n==0 ? pPreStyle : pUseStyle;
		pSty = new TStyleItem;

		fread( &pSty->iType, sizeof(char), 1, pFile );
		fread( &idStyItemStyle, sizeof(UINT), 1, pFile );

		fread( &pSty->nBars, sizeof(int), 1, pFile );
		int nSegNum[4];
		fread( nSegNum, sizeof(int), 4, pFile );
		for( int i=0; i<4; i++ ){
			pSty->nSegNum[i] = nSegNum[i];
		}

		DWORD iOpt;
		fread( &num, sizeof(int), 1, pFile );
		for( int i=0; i<num; i++ ){
			fread( &iOpt, sizeof(DWORD), 1, pFile );
		}

		TOpusStage* pStage = NULL;
		TSegmentItem* pSegPrev = NULL;
		fread( &num, sizeof(int), 1, pFile );
		for( int i=0; i<num; i++ ){
			if( n>0 )
				pStage = g_lstOpusStages[i];

			int idSegItemStyle;
			TSegmentItem* pSeg = new TSegmentItem;
			pSeg->bAutoSpec = n==0;

			fread( &pSeg->iType, sizeof(char), 1, pFile );
			fread( &idSegItemStyle, sizeof(UINT), 1, pFile );

			fread( &pSeg->iSegType, sizeof(char), 1, pFile );
			fread( &pSeg->iSegNo, sizeof(char), 1, pFile );
			if( pSeg->iSegType>=SEGTYPE_INTRO ){
				if( pSeg->iSegNo % 2 )
					pSeg->iSegNo = pSeg->iSegNo/2 + 4;
				else
					pSeg->iSegNo /= 2;
			}

			fread( &pSeg->iInd, sizeof(char), 1, pFile );
			fread( &pSeg->volume, sizeof(char), 1, pFile );
			fread( &pSeg->nBars, sizeof(int), 1, pFile );
			fread( pSeg->aChanUsed, sizeof(bool), 16, pFile );

			if( n>0 ){
				pStage = g_lstOpusStages[i];
				pStage->nVol = pSeg->volume;
			}

			//Options
			int count;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				fread( &iOpt, sizeof(DWORD), 1, pFile );
			}

			pSeg->aOptions->Add( (void*)OPT_DEL );
			pSeg->aOptions->Add( (void*)OPT_VOL );
			if( pSeg->iType<SEGTYPE_INTRO )
				pSeg->aOptions->Add( (void*)OPT_BRUSH );

			TTrackItem* pTrkPrev = NULL;
			fread( &count, sizeof(int), 1, pFile );
			for( int j=0; j<count; j++ ){
				int idTrkItemStyle;
				TTrackItem* pTrk = new TTrackItem;
				TTrack* pTrack = new TTrack;

				fread( &pTrk->iType, sizeof(char), 1, pFile );
				fread( &idTrkItemStyle, sizeof(UINT), 1, pFile );

				char iSegType;
				fread( &iSegType, sizeof(char), 1, pFile );
	//			fread( &pTrk->iSegType, sizeof(char), 1, pFile );
				fread( &pTrack->iSegNo, sizeof(char), 1, pFile );
				if( iSegType>=SEGTYPE_INTRO ){
					if( pTrack->iSegNo % 2 )
						pTrack->iSegNo = pTrack->iSegNo/2 + 4;
					else
						pTrack->iSegNo /= 2;
				}
				fread( &pTrack->iChanNo, sizeof(char), 1, pFile );
				fread( &pTrack->iChanSpec, sizeof(char), 1, pFile );
				fread( &pTrack->iProg, sizeof(char), 1, pFile );
				fread( &pTrack->iProgOrig, sizeof(char), 1, pFile );
				fread( &pTrack->nVol, sizeof(char), 1, pFile );
				fread( &pTrack->nVolOrig, sizeof(char), 1, pFile );

				bool bMute = false;
				fread( &bMute, sizeof(bool), 1, pFile );
				if( bMute )
					pTrack->nVol |= 0x80;

				int cn;
				fread( &cn, sizeof(int), 1, pFile );
				for( int k=0; k<cn; k++ ){
					fread( &iOpt, sizeof(DWORD), 1, pFile );
				}

				//检查轨道风格
				pTrk->pStyle = CheckStyle( 0, idTrkItemStyle );
				if( pTrk->pStyle ){
					pTrk->aOptions->Add( (void*)OPT_DEL );
					pTrk->aOptions->Add( (void*)OPT_VOL );

					if( pSeg->iSegType<=SEGTYPE_FILL )
						pTrk->aOptions->Add( (void*)OPT_TEXTURE );

					if( n==0 ){
						pTrk->aOptions->Add( (void*)OPT_FONTPROG );

						pTrack->iStyleLoc = 0;
						pTrack->iStyleId = idTrkItemStyle;
						pTrk->pTrack = pTrack;
						pTrk->bOwnTrack = true;
					}
					else if( pStage ){
						TTrack* pTrackSet = pStage->aTracks[j];
						pTrackSet->iProgOrig = pTrack->iProgOrig;
						pTrackSet->nVolOrig = pTrack->nVolOrig;
						pTrackSet->nVol = pTrack->nVol;

						pTrk->pTrack = pTrackSet;
						delete pTrack;
					}

					pTrk->up = pSeg;
					if( pTrkPrev ){
						pTrk->prev = pTrkPrev;
						pTrkPrev->next = pTrk;
					}
					pTrkPrev = pTrk;

					pSeg->aItems->Add( pTrk );
				}
				else{
					delete pTrk;
					delete pTrack;
					delete pSeg;

					if( n>0 ){
						bInvalid = true;
						goto STYLE_LOAD_OVER;
					}
				}
			}

			if( pSeg->nBars==0 && pSeg->iType>=SEGTYPE_INTRO ){
				TPROSTYLE* info = CheckStyle( 0, idSegItemStyle );
				if( !info && pSeg->aItems->Count>0 ){
					info = ((TTrackItem*)pSeg->aItems->Items[0])->pStyle;
				}

				if( info ){
					if( pSeg->iSegType==SEGTYPE_INTRO )
						pSeg->nBars = info->pOrigin->detail.aIntroBars[pSeg->iSegNo];
					else if( pSeg->iSegType==SEGTYPE_ENDING )
						pSeg->nBars = info->pOrigin->detail.aEndingBars[pSeg->iSegNo];
				}
			}

			if( n==0 && pSeg->aItems->Count==0 ){
				delete pSeg;
			}
			else{
				pSeg->up = pSty;
				if( pSegPrev ){
					pSeg->prev = pSegPrev;
					pSegPrev->next = pSeg;
				}
				pSegPrev = pSeg;

				pSty->aItems->Add( pSeg );
			}
		}

		TPROSTYLE* info = CheckStyle( 0, idStyItemStyle );
		if( !info && pSty->aItems->Count>0 ){
			for( int i=0; i<pSty->aItems->Count; i++ ){
				TSegmentItem* pSeg = (TSegmentItem*)pSty->aItems->Items[i];

				if( pSeg->aItems->Count>0 ){
					info = ((TTrackItem*)pSeg->aItems->Items[0])->pStyle;
					break;
				}
			}
		}

		if( info && ( pSty->aItems->Count>0 || n>0 ) ){
			pSty->pStyle = info;

			if( n==0 ){
				pSty->aOptions->Add((void*)OPT_FONTPROG);
				pSty->aOptions->Add((void*)OPT_SAVE);
			}
		}
		else{
			delete pSty;
			pSty = NULL;

			if( n>0 ){
				bInvalid = true;
				goto STYLE_LOAD_OVER;
			}
		}
	}

STYLE_LOAD_OVER:
	if( bInvalid ){
		if( pPreStyle ){
			delete pPreStyle;
		}

		if( pUseStyle ){
			delete pUseStyle;
		}

		return E_PROJ_INVALIDSTYLE;
	}
	else{
		g_pPreStyle = pPreStyle;
		g_pUseStyle = pUseStyle;
	}

	g_Theme.Build( lstBars, lstStages );

	//段落预设
	fread( &g_iPreStage, sizeof(int), 1, pFile );
	//视图模式
	int iViewMode;
	fread( &iViewMode, sizeof(int), 1, pFile );

	//预设工程
	if( wMinVersion>=3 )
		fread( &g_bPredefine, sizeof(bool), 1, pFile );

	return iError;
}

int LoadVersion2( FILE *pFile, DWORD dwVersion, HWND hNotifyWnd, int iLoadMode )
{
	int nSize, iMelodyKey, iMelodyTimeSignature, nMelodyTempo, nMelodyBarNum,
		nMelodyStageNum, nComposeStageNum, nCompleteBarNum;
	char strFont[MAX_PATH];
	string strStyleName;
	bool bUseful;
	int iError = E_PROJ_NOERROR;
	WORD wMinVersion = LOWORD( dwVersion );

	// 主要参数
	UINT idStyle = 0, iStyleType;
	fread(&iStyleType, sizeof(DWORD), 1, pFile); //风格类型
	fread(&idStyle, sizeof(UINT), 1, pFile);

	if( wMinVersion!=3 ){
		fread(&g_bMidiMelody, sizeof(bool), 1, pFile);
	}

	fread(&iMelodyTimeSignature, sizeof(int), 1, pFile);
	fread(&nMelodyTempo, sizeof(int), 1, pFile);
	fread(&iMelodyKey, sizeof(int), 1, pFile);

	if( g_iMelodyTimeSignature!=iMelodyTimeSignature ){
		SetMelodyTS(iMelodyTimeSignature);
		SelectStyle();
		PostMessage( Application->MainFormHandle, UM_CHANGETT, true, -1 );
	}

	TPROSTYLE* pStyle = CheckStyle( 0, idStyle );//GetStyleInfo( 0, idStyle );
	if( !pStyle )
		return E_PROJ_INVALIDSTYLE;

	SetMelodyTempo(nMelodyTempo);
	g_iMelodyKey = iMelodyKey;

	// 读取音色库文件名
	fread(&nSize, sizeof(int), 1, pFile);

	if( nSize>0 ){
		fread(strFont, sizeof(char), nSize, pFile);
		strcpy( g_strSoundFont, strFont );
	}

	// 各项音量设值
	fread(&g_fRecordVolume, sizeof(float), 1, pFile);
	if( g_fRecordVolume>1 ) g_fRecordVolume = 1;
	if( g_fRecordVolume<0 ) g_fRecordVolume = 0;

	fread(&g_fSpeakerVolume, sizeof(float), 1, pFile);
	if( g_fSpeakerVolume>1 )  g_fSpeakerVolume= 1;
	if( g_fSpeakerVolume<0 )  g_fSpeakerVolume= 0;

	float fAudioVolume = 1;
	fread(&fAudioVolume, sizeof(float), 1, pFile);
	if( fAudioVolume>1 ) fAudioVolume = 1;
	if( fAudioVolume<0 ) fAudioVolume = 0;

	fread(&g_fMusicVolume, sizeof(float), 1, pFile);
	if( g_fMusicVolume>1 ) g_fMusicVolume = 1;
	if( g_fMusicVolume<0 ) g_fMusicVolume = 0;

	f_MM_SetStreamVolume( 0, g_fSpeakerVolume );
	f_MM_SetStreamVolume( 1, g_fRecordVolume );
	f_MM_SetStreamVolume( 4, g_fMusicVolume );

	// 建立初始段落变量
	TBarList lstBars;
	vector<int> lstStages;

	// g_lstRawBars
	int num;
	fread( &num, sizeof(int), 1, pFile );
	if( num>0 ){
		for( int i=0; i<num; i++ ){
			TBar* pBar = new TBar;

			char iChords[2], iFill;
			fread(&iChords[0], sizeof(char), 1, pFile);
			fread(&iChords[1], sizeof(char), 1, pFile);

			pBar->aChords.iKey[0] = pBar->aChords.iKey[1]
								= (iChords[0] / 4 + iMelodyKey) % KEY_NUM;
			pBar->aChords.iType[0] = pBar->aChords.iType[1] = iChords[0] % 4;

			if( iChords[1]==-1 ){
				pBar->aChords.iKey[2] = pBar->aChords.iKey[3] =  pBar->aChords.iKey[0];
				pBar->aChords.iType[2] = pBar->aChords.iType[3] = pBar->aChords.iType[0];
			}
			else{
				pBar->aChords.iKey[2] = pBar->aChords.iKey[3]
									= (iChords[1] / 4 + iMelodyKey) % KEY_NUM;;
				pBar->aChords.iType[2] = pBar->aChords.iType[3] = iChords[1] % 4;
			}

			pBar->iBarKey = iMelodyKey;
			lstBars.push_back( pBar );

			fread(&iFill, sizeof(char), 1, pFile);

			TWaveBar* pWvBar = new TWaveBar;

			if( iLoadMode!=PROJ_MODE_UPLOAD || wMinVersion<8 )
				fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );

			if( iLoadMode==PROJ_MODE_UPLOAD )
				delete pWvBar;
			else
				g_aAudioTracks[0]->lstBars.push_back( pWvBar );
		}

		AudioEffectsDefault( 0, false );
		g_aAudioTracks[0]->volume = (int)(fAudioVolume * 100);
	}

	// g_lstRawStages
	fread( &num, sizeof(int), 1, pFile );
	for( int i=0; i<num; i++ ){
		int iFirstBar, iLastBar, iVar;
		fread(&iFirstBar, sizeof(int), 1, pFile);
		fread(&iLastBar, sizeof(int), 1, pFile);
		fread(&iVar, sizeof(int), 1, pFile);

		lstStages.push_back( iLastBar );
	}

	// g_lstOpusStages
	TAudioTrack* pAudioTrack = NULL;

	fread( &num, sizeof(int), 1, pFile );
	if( num>0 ){
		if( iLoadMode!=PROJ_MODE_UPLOAD ){
			pAudioTrack = new TAudioTrack;
			pAudioTrack->volume = (int)(fAudioVolume * 100);
			g_aAudioTracks.push_back( pAudioTrack );
			g_aAudioTracks[0]->Hide();// = true;
		}

		for( int i=0; i<num; i++ ){
			vector<int> lstSegType, lstSegNo, lstSegBars;
			int iMelodyStage, nStageBars, iVar, idStageStyle;

			fread( &iMelodyStage, sizeof(int), 1, pFile );
			fread( &nStageBars, sizeof(int), 1, pFile );
			fread( &iVar, sizeof(int), 1, pFile );
			fread( &idStageStyle, sizeof(UINT), 1, pFile );

			vector<int> lstFill;
			int nFillNum;
			fread(&nFillNum, sizeof(int), 1, pFile);
			for (int j = 0; j < nFillNum; j++) {
				DWORD dwFill;
				fread(&dwFill, sizeof(DWORD), 1, pFile);
				lstFill.push_back( dwFill );
			}

			TPROSTYLE* pStageStyle = CheckStyle( 0, idStageStyle );

			if( !pStageStyle ){
				idStageStyle = idStyle;
				pStageStyle = pStyle;

				iError |= E_PROJ_INVALSTAGESTYLE;
			}

			int iBarStart = 0;
			if( iMelodyStage<0x100 ){ //伴奏
				if( iMelodyStage>0 )
					iBarStart = lstStages[iMelodyStage-1] + 1;

				if( nFillNum>0 ){
					int iBar = 0;
					for( int j=0; j<nFillNum; j++ ){
						int iPos = LOWORD(lstFill[j]),
							iNo =	HIWORD(lstFill[j]);
						if( iPos>iBar ){
							lstSegType.push_back( SEGTYPE_VAR );
							lstSegNo.push_back( iVar );
							lstSegBars.push_back( iPos-iBar );
						}

						lstSegType.push_back( SEGTYPE_FILL );
						lstSegNo.push_back( iNo );
						lstSegBars.push_back( 1 );

						iBar = iPos+1;
					}
				}
				else{
					lstSegType.push_back( SEGTYPE_VAR );
					lstSegNo.push_back( iVar );
					lstSegBars.push_back( nStageBars );
				}
			}
			else if( iMelodyStage<0x110 ){ //前奏
				lstSegType.push_back( SEGTYPE_INTRO );
				int iNo = iMelodyStage - 0x100;
				lstSegNo.push_back( iNo );
				lstSegBars.push_back( nStageBars );

			}
			else{ //尾奏
				lstSegType.push_back( SEGTYPE_ENDING );
				int iNo = iMelodyStage - 0x110;
				lstSegNo.push_back( iNo );
				lstSegBars.push_back( nStageBars );
			}

			for( int k=0; k<lstSegType.size(); k++ ){
				TOpusStage* pStage = new TOpusStage;

				pStage->iSegKey = iMelodyKey;
				pStage->iSegType = lstSegType[k];
				pStage->iSegNo = lstSegNo[k];
				pStage->nVol = 100;

				for( int j=0; j<lstSegBars[k]; j++ ){
					TBar* pBar = new TBar;
					pStage->aBars.push_back( pBar );

					TWaveBar* pWvBar = NULL;
					if( pAudioTrack ){
						pWvBar = new TWaveBar;
						pAudioTrack->lstBars.push_back( pWvBar );
					}

					pBar->iBarKey = iMelodyKey;
					if( pStage->iSegType<SEGTYPE_INTRO ){
						memcpy( pBar, lstBars[iBarStart], sizeof(TBar) );

						if( pWvBar )
							memcpy( pWvBar, g_aAudioTracks[0]->lstBars[iBarStart],
													sizeof(DWORD)*POINTS_PER_BAR );

						iBarStart++;
					}
				}

				//前/间/尾奏小调修正
				if( pStage->iSegType<SEGTYPE_INTRO ){
					int cType = pStage->aBars[0]->aChords.iType[0];
					if( cType==1 || cType==3 ){
						for( int j=g_lstOpusStages.size()-1; j>=0; j-- ){
							if( g_lstOpusStages[j]->iSegType==SEGTYPE_INTRO ){
								if( g_lstOpusStages[j]->iSegNo<4 ){
									g_lstOpusStages[j]->iSegNo += 4;

									for( int t=0; t<g_lstOpusStages[j]->aTracks.size(); t++ ){
										TTrack* pTrk = g_lstOpusStages[j]->aTracks[t];
										pTrk->iSegNo += 4;
									}
								}
							}
							else{
								break;
							}
						}
					}
				}
				else if( !g_lstOpusStages.empty() ){
					if( g_lstOpusStages.back()->iSegType<SEGTYPE_INTRO ){
						int cType = g_lstOpusStages.back()->aBars[0]->aChords.iType[0];
						if( cType==1 || cType==3 ){
							pStage->iSegNo += 4;
						}
					}
					else if( g_lstOpusStages.back()->iSegNo>=4 )
						pStage->iSegNo += 4;
				}

				TSTYLEDETAIL& detail = pStageStyle->pOrigin->detail;
				for( int j=0; detail.tracks[lstSegType[k]][lstSegNo[k]][j].no>=0; j++ ){
					TTrack* pTrack = new TTrack;
					pTrack->iStyleId = idStageStyle;
					pTrack->iSegNo = pStage->iSegNo;
					pTrack->iChanNo = pTrack->iChanSpec
								= detail.tracks[lstSegType[k]][lstSegNo[k]][j].no;
					pTrack->iProg = pTrack->iProgOrig
								= detail.tracks[lstSegType[k]][lstSegNo[k]][j].prog;
					pTrack->nVol = pTrack->nVolOrig
								= detail.tracks[lstSegType[k]][lstSegNo[k]][j].vol;

					pStage->aTracks.push_back( pTrack );
				}


				g_lstOpusStages.push_back( pStage );
			}
		}

		g_Opus.CountBars();
	}

	// 全曲录音信息
	int iComposeKey;
	fread(&iComposeKey, sizeof(int), 1, pFile);

	// 全曲小节音量
	fread(&nCompleteBarNum, sizeof(int), 1, pFile);
	if( nCompleteBarNum ){
		for( int i=0; i<nCompleteBarNum; i++ ){
			TWaveBar barWave;
			TWaveBar* pWvBar = pAudioTrack ? pAudioTrack->lstBars[i] : &barWave;
			fread( pWvBar->aVols, sizeof(DWORD), POINTS_PER_BAR, pFile );
		}
	}

	for( int n=0; n<2; n++ ){
		TStyleItem* pSty = new TStyleItem;

		pSty->pStyle = pStyle;

		if( n==0 ){
			pSty->aOptions->Add((void*)OPT_FONTPROG);
			pSty->aOptions->Add((void*)OPT_SAVE);
			g_pPreStyle = pSty;
		}
		else{
			g_pUseStyle = pSty;
		}
	}

	g_Theme.Build( lstBars, lstStages );

	// 所处页面
	int iPage;
	fread(&iPage, sizeof(int), 1, pFile);
 /*	if( iPage==2 )
		g_iViewMode = 2;
	else if( iPage==1 || iPage==4 )
		g_iViewMode = 1;
	else
		g_iViewMode = 3;
*/
	g_iPreStage = 3;

	//音效
	int nFxNum;
	fread( &nFxNum, sizeof(int), 1, pFile );
	if( nFxNum>0 ){
		int aAudioEffects[11];
		fread( aAudioEffects, sizeof(int), nFxNum, pFile );

		if( pAudioTrack ){
			for( int i=0; i<MAX_FX_NUM; i++ ){
				if( aAudioEffects[i]>0 ){
					int iType = g_aAudioEffectTypes[i];

					if( iType!=FX_PITCH ){
						int nSize = GetFxParamNum( iType );
						float* pParams = new float[nSize];
						int iPreset = aAudioEffects[i] - 1;

						GetFxPreset( iType, iPreset, pParams );

						TAudioFx* pFx = new TAudioFx( iType, iPreset, pParams, nSize );
						pAudioTrack->lstFxs.push_back( pFx );
					}
				}
			}
		}
	}
	else if( pAudioTrack ){
		AudioEffectsDefault( 1, false );
	}

	//预设工程
	if( wMinVersion>=5 )
		fread( &g_bPredefine, sizeof(bool), 1, pFile );

	return iError;
}

BOOL HasProjectModified( bool bAuto )
{
	if( g_Undo.GetLastLite()!=(bAuto ? u_pAutoLite : u_pProjLite))
		return TRUE;

	if( bAuto || g_Theme.Empty() )
		return FALSE;

	if( g_bProjStylePaid || g_fRecordVolume_SVD != g_fRecordVolume
				|| g_fSpeakerVolume_SVD != g_fSpeakerVolume
				|| g_iMelodyKey_SVD != g_iMelodyKey
				|| g_nMelodyTempo_SVD != g_nMelodyTempo
				//|| g_strFontFile_SVD.compare(g_strFontFile) ){
				|| strcmp( g_strSoundFont_SVD, g_strSoundFont )){
		return TRUE;
	}

	return FALSE;
}

void ClearSVDVars() {
	//g_strFontFile_SVD.clear();
	g_strSoundFont_SVD[0] = 0;
	g_iMelodyKey_SVD = -1;
	g_nMelodyTempo_SVD = g_nMelodyTempo;
	g_fRecordVolume_SVD = g_fRecordVolume;
	g_fSpeakerVolume_SVD = g_fSpeakerVolume;
}

void UpdateSVDVars()
{
	ClearSVDVars();

	// 旋律主要信息
	g_iMelodyKey_SVD = g_iMelodyKey;
	g_nMelodyTempo_SVD = g_nMelodyTempo;

	// 音色库
	//g_strFontFile_SVD = g_strFontFile;
	strcpy( g_strSoundFont_SVD, g_strSoundFont );

	// 各项音量设值
	g_fRecordVolume_SVD = g_fRecordVolume;
	g_fSpeakerVolume_SVD = g_fSpeakerVolume;
}

int CanSaveProj()
{
//	int ret = E_PROJ_NOERROR;
/*
	bool bHasUnlocalStyle = false;
	for( int i=0; !bHasUnlocalStyle && i<g_lstOpusStages.size(); i++ ){
		TOpusStage *pStage = g_lstOpusStages[i];
		for( int j=0; j<pStage->aTracks.size(); j++ ){
			if( pStage->aTracks[j]->iStyleLoc==(UINT)-1
							&& pStage->aTracks[j]->iStyleId!=0 ){
				bHasUnlocalStyle = true;
				break;
			}
		}
	}

	if( bHasUnlocalStyle )
		return E_PROJ_NOLOCALTEMPSTYLE;
*/
	if( g_pUseStyle && (!g_pUseStyle->pStyle || GetStyleInfo( -1, 0 )) )
		return E_PROJ_UNSAVEDTEMPSTYLE;


	return E_PROJ_NOERROR;
}

void ClearAutoProj()
{
	SetAutoSaveReg( false );

	if( FileExists( g_strAutoProjName.c_str() ) )
		DeleteFile( g_strAutoProjName.c_str() );

	DebugPrint("delete auto Save project file....");
}

void SaveAutoProj()
{
	if( HasProjectModified(true) && CanSaveProj()==E_PROJ_NOERROR ){
		DebugPrint("auto Save project....");
		AnsiString strProjectName = g_strAutoProjName.c_str();

		SaveProject( strProjectName.c_str() );
	}
}

