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

#include <mmsystem.h>
#include "GlobalUnit.h"
#include "MessageDef.h"
#include "FxDef.h"
#include "StyleItem.h"
#include "Project.h"
#include "Undo.h"
#include "MidiTrack.h"
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
// ---------------------------------------------------------------------------
#pragma package(smart_init)

#define EX_NULL				= NULL
#define MAX_STYLE_CACHE 	32

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

/*************************************************************************************** /
 // 全局常量
/************************************************************************************** */
const char *g_strDefaultSoundSet = "Pro default",
	*g_strCZFont[18] = { "CZ 钢琴组", "CZ 色彩打击乐", "CZ 风琴组", "CZ 吉他组", "CZ 贝司组",
			"CZ 弦乐组", "CZ 合奏合唱", "CZ 铜管组", "CZ 簧管组", "CZ 笛组", "CZ 合成主音",
			"CZ 合成背景", "CZ 合成效果", "CZ 民间乐器", "CZ 打击乐器", "CZ 声音效果",
			"CZ 鼓组", "CZ 中国风" },
	*g_strMelodyKey[KEY_NUM] = {
			"C", "bD", "D", "bE", "E", "F", "#F", "G", "bA", "A", "bB", "B"}, // 调号显示
	*g_strTimeSignature[4] = {"4/4", "3/4", "2/4", "6/8"}, // 拍号
	*g_strTSName[4] = {"44", "43", "42", "86"}, // 拍号命名
	*g_strSegment[4] = { "伴奏", "加花", "前/间奏", "尾奏" },
	*NAME_SEG[] = {	{"V"},	{"F"},	{"I"},	{"E"}, },
	*g_strIntro[MAX_INTRO_NUM] = {"前/间奏-1", "前/间奏-2", "前/间奏-3",
								"前/间奏-4"	}, // 插入段显示文字
	*g_strEnding[MAX_ENDING_NUM] = {"尾奏-1", "尾奏-2", "尾奏-3", "尾奏-4"},
	*g_strFill[STAGE_FILL_NUM] = {"加花-1", "加花-2", "加花-3", "加花-4"}, // 加花小节显示文字
	*g_strStageVar[STAGE_VAR_NUM] = {"伴奏-1","伴奏-2","伴奏-3","伴奏型-4"}, // 分段伴奏型文字
	*g_strStage = "%c段"; // 旋律段显示文字

const String g_strTable[7] = { L"Ⅰ", L"Ⅱ", L"Ⅲ", L"Ⅳ", L"Ⅴ", L"Ⅵ", L"Ⅶ" },
		g_strAlphaTable[7] = { L"C", L"D", L"E", L"F", L"G", L"A", L"B" };

/*
const TColor g_clrSegment[4][8] = {{RGB(250,244,213),RGB(248,235,159), // 伴奏颜色
									RGB(247,224,128),RGB(244,205,100),
									RGB(246,187,95),RGB(246,172,82),
									RGB(244,149,64),RGB(234,132,59)},
									{RGB(254,214,247),RGB(246,193,241),  // 加花颜色
									RGB(240,172,236),RGB(238,149,234),
									RGB(236,111,231),RGB(236,75,231),
									RGB(236,47,231),RGB(224,15,231)},
									{RGB(196,230,147),RGB(179,215,176),  // 前奏颜色
									RGB(164,200,161),RGB(148,185,145)},
									{RGB(203,219,247),RGB(189,206,230),  // 尾奏颜色
									RGB(177,193,220),RGB(164,180,205)}};
*/

/*************************************************************************************** /
 // 全局变量
/************************************************************************************** */
FONTINFOLIST 	g_lstFonts; // 音色库列表
FONTINFO*		g_lstCZFonts[18]; //扩展音色库
VSTINFOLIST		g_lstVSTFx,				//VST音效列表
				g_lstVSTi;				//VSTi音色库列表

STYLELIST		g_aOriginStyles, // 在线风格列表
				g_aLocalStyles,  // 本地风格列表
				g_aShareStyles,	 // 分享风格列表
				g_aTempStyles,	 // 临时风格列表
				g_aCollectStyles, // 收藏风格列表
				g_aRecomStyles,	 // 推荐风格列表
				u_aCacheStyles;  // 风格列表缓存

wstring g_strVSTPath, // VST路径
	g_strVSTiPath,    // VSTi路径
	g_strLastSavePath, // 上次保存音乐文件名
	g_strLastImportFile, // 上次导入旋律文件名
	g_strExecutePath, // 执行文件路径
	g_strUserPath,	  // 用户路径
	g_strExtFontsPath, //扩展音色库路径
	g_strSegImportPath;		// 导入片段路径

string g_strSelectedStyleName; // 选中风格名
vector<int>g_lstStyleSelected; // 选中风格类型集合
DWORD g_iSelectedStyleType = 0; // 选定风格类型

char g_strTxtFontName[20] = "Tahoma",
	g_strSoundFont[80] = "", 		//全局音色库名称
	g_strCurrentVersion[20] = "",
	g_strServerURL[256] = "",
	g_strPlaybackDevice[256] = "",
	g_strRecordDevice[256] = "";

int g_arrIntroBarNum[MAX_INTRO_NUM], // 全局风格前间奏小节数
	g_arrEndingBarNum[MAX_ENDING_NUM], // 全局风格尾奏小节数

	g_idFont = -1, // 选中音色库序号
	g_iFontType = 0, // 色库类型 SF2/VST
	g_iMelodyTimeSignature = 0, // 主旋律拍号
	g_nMelodyTempo = 75, // 主旋律速度
	g_nChordNumPerBar = 4, //每小节和弦数
	g_nBPM = 4,			   	// 每小节拍数
	g_nPPB = 30,			// 每拍点数

	g_iPlaybackDevice = -1,	// 指定播放设备号
	g_iPlaybackOutput = -1,	// 指定播放输出源
	g_iRecordDevice = -1, //指定录音设备号
	g_iRecordInput = -1, //录音输入源
	g_nRecordChannels = 1, //缺省单通道录音
	g_iToolPanelShow = 0,  // 工具面板显示方式（0=右边，1=左边, 2=隐藏）
	g_iLastSaveOption = SAVE_COMPOSE | SAVE_AUDIO, // 上次保存选项，缺省为全部
	g_iLastSaveType = FILETYPE_MP3, // 上次保存文件格式，缺省为MP3
	g_iViewMode = 0, // 视图模式，缺省为风格
	g_iPreStage = 2,  // 预设段落模式，缺省为IMIME
	g_iPreStageDefault = 2, // 用户预设段落模式，缺省为IMIME
	g_iSegColorMode = 1,	// 段落色彩模式（0=风格段号，1=轨道数）

	g_iWindowState = wsNormal;

float g_fRecordVolume = -1, // 录音音量
	g_fSpeakerVolume = -1; // 喇叭音量

double g_dblStep = 0, g_dblTimePerBar = 0;

TUSERINFO 		g_infoUser;
TSOFTWAREINFO 	g_infoSoftwareUpdate;
TSONGINFO		g_infoSong;

bool
	g_bRecordAutoAdjust = true, //录音自动音量调节
	g_bRecordMoniter = false,  	//不启用录音监听
	g_bShowRecordHint = true, // 噪音侦测
	g_bUpdateMandatory = false, // 客户端需要强制更新
	g_bMidiMelody = false, //导入MIDI旋律
	g_bWeakup = false, // 旋律弱起
	g_bShowPlayTick = true, // 显示小节节拍或时间
	g_bAutoLogin = true,
	g_bLogon = false,
	g_bPredefine = false, // 预设工程（不自动编曲/接唱）
	g_bRecProtect = false,	// 内录保护
	g_bShowProtectMsg = true, //显示内录保护消息
	g_bShowVSTPath = true,	  //是否提示设置VST路径
//	g_bSongSaved = false,	//全曲已保存
	g_bAudioChanged = false, // 初始录音修改
	g_bSongChanged = false, // 全曲录音修改

//	g_bRightPanelShow = true, //是否显示右边栏
	g_bAlphaKey = false, 	// false,罗马，true，英文
	g_bAutoSave = false,    //自动保存
	g_bAutoDownloadStyle = false,	//自动下载风格
	g_bAutoOpenProject = false,		//自动打开上次工程
	g_bAutoOpenProjectEnable = false,//自动打开上次工程使能
	g_bProjStylePaid = false,		//工程风格支付更改
	g_bPrebeat = false,				//使用预设风格节拍提示
	g_bExtFontUsable = false,		//扩展音色库可用
	g_bExtFont = false;				//使用扩展音色库

//DWORD			   	g_iMacAddressNum = 0;   //mac地址个数
vector<char *>		g_lstMacAddress;        //mac地址
//vector<char *>		g_lstMacAddressNew;

UINT g_xDpi=96, g_yDpi=96;  //High DPI 自适应
int     g_szFont7 = 7,
		g_szFont8 = 8,
		g_szFont9 = 9,
		g_szFont10 = 10,
		g_szFont11 = 11,
        g_szFont12 = 12,
		g_szFont16 = 16;
/*************************************************************************************** /
 // 全局函数声明
/************************************************************************************** */
CM_GetVersion			f_CM_GetVersion EX_NULL;
CM_Initialize  			f_CM_Initialize EX_NULL;
CM_Release 				f_CM_Release EX_NULL;
CM_CheckStyle 			f_CM_CheckStyle EX_NULL;
CM_GetStyleRecomIDs 	f_CM_GetStyleRecomIDs EX_NULL;
CM_GetStyleInfo 		f_CM_GetStyleInfo EX_NULL;
CM_GetStyleInfos 		f_CM_GetStyleInfos EX_NULL;
CM_SetMelodyNotes 		f_CM_SetMelodyNotes EX_NULL;
CM_AutoChords 			f_CM_AutoChords EX_NULL;
CM_Compose 				f_CM_Compose EX_NULL;
CM_GetNextLocalID		f_CM_GetNextLocalID EX_NULL;
CM_SaveLocalStyle		f_CM_SaveLocalStyle EX_NULL;
CM_ChangeLocalStyle		f_CM_ChangeLocalStyle EX_NULL;
CM_DeleteLocalStyle		f_CM_DeleteLocalStyle EX_NULL;
CM_AddTempSegment		f_CM_AddTempSegment EX_NULL;
CM_DeleteTempSegment	f_CM_DeleteTempSegment EX_NULL;
CM_DeleteTempStyle		f_CM_DeleteTempStyle EX_NULL;
CM_ProjBackupStyle		f_CM_ProjBackupStyle EX_NULL;
CM_ProjRestoreStyle		f_CM_ProjRestoreStyle EX_NULL;
CM_GetCollectionIDs		f_CM_GetCollectionIDs EX_NULL;
CM_SetCollectionStyle	f_CM_SetCollectionStyle EX_NULL;
CM_MakeStyle 			f_CM_MakeStyle EX_NULL;

MM_GetVersion			f_MM_GetVersion EX_NULL;
MM_InitialObjects 		f_MM_InitialObjects EX_NULL;
MM_DestroyObjects 		f_MM_DestroyObjects EX_NULL;
MM_GetFontInfo 			f_MM_GetFontInfo EX_NULL;
MM_SetDefaultFont		f_MM_SetDefaultFont EX_NULL;
MM_GetVSTInfo			f_MM_GetVSTInfo EX_NULL;
MM_LoadVSTi				f_MM_LoadVSTi EX_NULL;
MM_HandleVSTiPreset		f_MM_HandleVSTiPreset EX_NULL;
MM_GetVSTiPrograms		f_MM_GetVSTiPrograms EX_NULL;
MM_LoadMidiMelody 		f_MM_LoadMidiMelody EX_NULL;
MM_LoadCompose 			f_MM_LoadCompose EX_NULL;
MM_FreeComposes			f_MM_FreeComposes EX_NULL;
MM_LoadPrebeat			f_MM_LoadPrebeat EX_NULL;
MM_Play 				f_MM_Play EX_NULL;
MM_Stop 				f_MM_Stop EX_NULL;
MM_CheckIODevice     	f_MM_CheckIODevice EX_NULL;
MM_SetIODevice	     	f_MM_SetIODevice EX_NULL;
MM_GetPlaybackDeviceInfo	f_MM_GetPlaybackDeviceInfo EX_NULL;
MM_GetPlaybackOutputInfo	f_MM_GetPlaybackOutputInfo EX_NULL;
MM_GetRecordDeviceInfo 	f_MM_GetRecordDeviceInfo EX_NULL;
MM_GetRecordInputInfo 	f_MM_GetRecordInputInfo EX_NULL;
MM_RecordTest		 	f_MM_RecordTest EX_NULL;
MM_SetRecordAutoAdjust  f_MM_SetRecordAutoAdjust EX_NULL;
MM_SetRecordMoniter	    f_MM_SetRecordMoniter EX_NULL;
MM_GetMidiInBuffer	    f_MM_GetMidiInBuffer EX_NULL;
MM_SetMidiInBuffer	    f_MM_SetMidiInBuffer EX_NULL;
MM_SetRecordProtect   	f_MM_SetRecordProtect EX_NULL;
MM_ShowAsioPanel		f_MM_ShowAsioPanel EX_NULL;
MM_RestartAsioDevice	f_MM_RestartAsioDevice EX_NULL;
MM_LoadAudio 			f_MM_LoadAudio EX_NULL;
MM_GetMelodyInfo 		f_MM_GetMelodyInfo EX_NULL;
MM_GetMelodyBars		f_MM_GetMelodyBars EX_NULL;
MM_GetMelodyNotes		f_MM_GetMelodyNotes EX_NULL;
MM_CreateRealTimeMIDIStream f_MM_CreateRealTimeMIDIStream EX_NULL;
MM_FreeRealTimeMIDIStream f_MM_FreeRealTimeMIDIStream EX_NULL;
MM_RealTimeMIDINoteOn 	f_MM_RealTimeMIDINoteOn EX_NULL;
MM_RealTimeMIDINoteOff 	f_MM_RealTimeMIDINoteOff EX_NULL;
MM_LoadDemo				f_MM_LoadDemo EX_NULL;
MM_PlayDemo				f_MM_PlayDemo EX_NULL;
MM_ChangeDemoParam		f_MM_ChangeDemoParam EX_NULL;
MM_SetTempo 			f_MM_SetTempo EX_NULL;
MM_SetTimeSignature 	f_MM_SetTimeSignature EX_NULL;
MM_GetAudioVolume 		f_MM_GetAudioVolume EX_NULL;
MM_GetStreamVolume		f_MM_GetStreamVolume EX_NULL;
MM_SetStreamVolume 		f_MM_SetStreamVolume EX_NULL;
MM_GetLatency			f_MM_GetLatency EX_NULL;
MM_Save 				f_MM_Save EX_NULL;
MM_SaveMidi				f_MM_SaveMidi EX_NULL;
MM_SaveProject	        f_MM_SaveProject EX_NULL;
MM_LoadProject	        f_MM_LoadProject EX_NULL;
MM_ResetProject	        f_MM_ResetProject EX_NULL;
MM_UserCanceled			f_MM_UserCanceled EX_NULL;
MM_ActiveAPR			f_MM_ActiveAPR EX_NULL;
MM_SetTrackEvent	 	f_MM_SetTrackEvent EX_NULL;
MM_ShowVSTEditor 		f_MM_ShowVSTEditor EX_NULL;
MM_SaveVSTParams	 	f_MM_SaveVSTParams EX_NULL;
MM_AudioNewTrack	 	f_MM_AudioNewTrack EX_NULL;
MM_AudioDeleteTrack 	f_MM_AudioDeleteTrack EX_NULL;
MM_AudioRecord		 	f_MM_AudioRecord EX_NULL;
MM_AudioMove		 	f_MM_AudioMove EX_NULL;
MM_AudioFx	 	 		f_MM_AudioFx EX_NULL;
MM_AudioLoad	 	 	f_MM_AudioLoad EX_NULL;
MM_AudioGetLength 	 	f_MM_AudioGetLength EX_NULL;
MM_AddUndoBefore 		f_MM_AddUndoBefore EX_NULL;
MM_AddUndoAfter	 		f_MM_AddUndoAfter EX_NULL;
MM_CancelAddUndo 		f_MM_CancelAddUndo EX_NULL;
MM_Undo			 		f_MM_Undo EX_NULL;
MM_AudioAddFx	 		f_MM_AudioAddFx EX_NULL;
MM_AudioGetFxParam	 	f_MM_AudioGetFxParam EX_NULL;
MM_AudioSetFxParam	 	f_MM_AudioSetFxParam EX_NULL;
MM_AudioMoveFx	 		f_MM_AudioMoveFx EX_NULL;
MM_AudioFxProcess	 	f_MM_AudioFxProcess;
MM_SetMidiTrackParam	f_MM_SetMidiTrackParam EX_NULL;
MM_SetAudioTrackParam	f_MM_SetAudioTrackParam EX_NULL;

CS_GetVersion			f_CS_GetVersion EX_NULL;
CS_InitialService 		f_CS_InitialService EX_NULL;
CS_DestroyService 		f_CS_DestroyService EX_NULL;
CS_Register 			f_CS_Register EX_NULL;
CS_Login 				f_CS_Login EX_NULL;
CS_Logoff 				f_CS_Logoff EX_NULL;
CS_CheckPayment			f_CS_CheckPayment EX_NULL;
CS_ConfirmPayment		f_CS_ConfirmPayment EX_NULL;
CS_CancelOperation 		f_CS_CancelOperation EX_NULL;
CS_DownloadStyle 		f_CS_DownloadStyle EX_NULL;
CS_GetQnA  		 		f_CS_GetQnA EX_NULL;
CS_SubmitQnA   	 		f_CS_SubmitQnA EX_NULL;
CS_GetNotice   			f_CS_GetNotice EX_NULL;
CS_GetNewNoticeNum		f_CS_GetNewNoticeNum EX_NULL;
CS_UploadSong			f_CS_UploadSong EX_NULL;
CS_GetWebPageURL    	f_CS_GetWebPageURL EX_NULL;
CS_GetStyleNumsEx     	f_CS_GetStyleNumsEx EX_NULL;
CS_StyleScore         	f_CS_StyleScore EX_NULL;
CS_AutoDownloadStyle   	f_CS_AutoDownloadStyle EX_NULL;
CS_SaveProject         	f_CS_SaveProject EX_NULL;
CS_LoadProject         	f_CS_LoadProject EX_NULL;
CS_ResetProject	    	f_CS_ResetProject EX_NULL;
CS_UploadStyle	    	f_CS_UploadStyle EX_NULL;

QR_Encode 				f_QR_Encode 		EX_NULL;

/*************************************************************************************** /
 // 全局函数实现
/************************************************************************************** */
HRESULT GetCMFunctions(HINSTANCE hDll) {
	// VERIFY( hDll );

	f_CM_GetVersion = (CM_GetVersion)GetProcAddress(hDll, "CM_GetVersion");
	f_CM_Initialize = (CM_Initialize)GetProcAddress(hDll, "CM_Initialize");
	f_CM_Release = (CM_Release)GetProcAddress(hDll, "CM_Release");
	f_CM_CheckStyle = (CM_CheckStyle)GetProcAddress(hDll, "CM_CheckStyle");
	f_CM_GetStyleRecomIDs = (CM_GetStyleRecomIDs)GetProcAddress(hDll,"CM_GetStyleRecomIDs");
	f_CM_GetStyleInfo = (CM_GetStyleInfo)GetProcAddress(hDll, "CM_GetStyleInfo");
	f_CM_GetStyleInfos = (CM_GetStyleInfos)GetProcAddress(hDll,	"CM_GetStyleInfos");
	f_CM_SetMelodyNotes = (CM_SetMelodyNotes)GetProcAddress(hDll, "CM_SetMelodyNotes");
	f_CM_AutoChords = (CM_AutoChords)GetProcAddress(hDll, "CM_AutoChords");
	f_CM_Compose = (CM_Compose)GetProcAddress(hDll, "CM_Compose");
	f_CM_GetNextLocalID = (CM_GetNextLocalID)GetProcAddress(hDll, "CM_GetNextLocalID");
	f_CM_SaveLocalStyle = (CM_SaveLocalStyle)GetProcAddress(hDll, "CM_SaveLocalStyle");
	f_CM_ChangeLocalStyle = (CM_ChangeLocalStyle)GetProcAddress(hDll, "CM_ChangeLocalStyle");
	f_CM_DeleteLocalStyle = (CM_DeleteLocalStyle)GetProcAddress(hDll, "CM_DeleteLocalStyle");
	f_CM_AddTempSegment = (CM_AddTempSegment)GetProcAddress(hDll,"CM_AddTempSegment");
	f_CM_DeleteTempSegment = (CM_DeleteTempSegment)GetProcAddress(hDll, "CM_DeleteTempSegment");
	f_CM_DeleteTempStyle = (CM_DeleteTempStyle)GetProcAddress(hDll,"CM_DeleteTempStyle");
	f_CM_ProjBackupStyle = (CM_ProjBackupStyle)GetProcAddress(hDll, "CM_ProjBackupStyle");
	f_CM_ProjRestoreStyle = (CM_ProjRestoreStyle)GetProcAddress(hDll,"CM_ProjRestoreStyle");
	f_CM_GetCollectionIDs = (CM_GetCollectionIDs)GetProcAddress(hDll,"CM_GetCollectionIDs");
	f_CM_SetCollectionStyle = (CM_SetCollectionStyle)GetProcAddress(hDll, "CM_SetCollectionStyle");
	f_CM_MakeStyle = (CM_MakeStyle)GetProcAddress(hDll, "CM_MakeStyle");

	if (!(f_CM_Initialize && f_CM_Release && f_CM_CheckStyle && f_CM_GetStyleInfo &&
		f_CM_GetStyleInfos && f_CM_GetStyleRecomIDs && f_CM_SetMelodyNotes &&
		f_CM_AutoChords && f_CM_Compose && f_CM_GetNextLocalID && f_CM_SaveLocalStyle &&
		f_CM_DeleteLocalStyle && f_CM_AddTempSegment && f_CM_DeleteTempSegment &&
		f_CM_DeleteTempStyle && f_CM_ProjBackupStyle && f_CM_ProjRestoreStyle &&
		f_CM_GetCollectionIDs && f_CM_SetCollectionStyle && f_CM_MakeStyle &&
		f_CM_ChangeLocalStyle && f_CM_GetVersion )){
		return S_FALSE;
	}

	HRESULT hResult = f_CM_GetVersion();
	if( hResult!=CM_VERSION || f_CM_Initialize()!= S_OK ){
		return S_FALSE;
	}

	return S_OK;
}

HRESULT GetMMFunctions(HINSTANCE hDll) {
	// VERIFY( hDll );

	f_MM_GetVersion = (MM_GetVersion)GetProcAddress(hDll, "MM_GetVersion");
	f_MM_InitialObjects = (MM_InitialObjects)GetProcAddress(hDll, "MM_InitialObjects");
	f_MM_DestroyObjects = (MM_DestroyObjects)GetProcAddress(hDll, "MM_DestroyObjects");
	f_MM_GetFontInfo = (MM_GetFontInfo)GetProcAddress(hDll, "MM_GetFontInfo");
	f_MM_SetDefaultFont = (MM_SetDefaultFont)GetProcAddress(hDll, "MM_SetDefaultFont");
	f_MM_GetVSTInfo = (MM_GetVSTInfo)GetProcAddress(hDll, "MM_GetVSTInfo");
	f_MM_LoadVSTi = (MM_LoadVSTi)GetProcAddress(hDll, "MM_LoadVSTi");
	f_MM_GetVSTiPrograms = (MM_GetVSTiPrograms)GetProcAddress(hDll, "MM_GetVSTiPrograms");
	f_MM_HandleVSTiPreset = (MM_HandleVSTiPreset)GetProcAddress(hDll, "MM_HandleVSTiPreset");
	f_MM_LoadMidiMelody = (MM_LoadMidiMelody)GetProcAddress(hDll, "MM_LoadMidiMelody");
	f_MM_LoadCompose = (MM_LoadCompose)GetProcAddress(hDll, "MM_LoadCompose");
	f_MM_FreeComposes = (MM_FreeComposes)GetProcAddress(hDll, "MM_FreeComposes");
	f_MM_LoadPrebeat = (MM_LoadPrebeat)GetProcAddress(hDll, "MM_LoadPrebeat");
	f_MM_Play = (MM_Play)GetProcAddress(hDll, "MM_Play");
	f_MM_Stop = (MM_Stop)GetProcAddress(hDll, "MM_Stop");
	f_MM_CheckIODevice = (MM_CheckIODevice)GetProcAddress(hDll,  "MM_CheckIODevice");
	f_MM_SetIODevice = (MM_SetIODevice)GetProcAddress(hDll,  "MM_SetIODevice");
	f_MM_GetPlaybackDeviceInfo = (MM_GetPlaybackDeviceInfo)GetProcAddress(hDll,	"MM_GetPlaybackDeviceInfo");
	f_MM_GetPlaybackOutputInfo = (MM_GetPlaybackOutputInfo)GetProcAddress(hDll,	"MM_GetPlaybackOutputInfo");
	f_MM_GetRecordDeviceInfo = (MM_GetRecordDeviceInfo)GetProcAddress(hDll,	"MM_GetRecordDeviceInfo");
	f_MM_GetRecordInputInfo = (MM_GetRecordInputInfo)GetProcAddress(hDll, "MM_GetRecordInputInfo");
	f_MM_RecordTest = (MM_RecordTest)GetProcAddress(hDll, "MM_RecordTest");
	f_MM_SetRecordAutoAdjust = (MM_SetRecordAutoAdjust)GetProcAddress(hDll, "MM_SetRecordAutoAdjust");
	f_MM_SetRecordMoniter = (MM_SetRecordMoniter)GetProcAddress(hDll, "MM_SetRecordMoniter");
	f_MM_GetMidiInBuffer = (MM_GetMidiInBuffer)GetProcAddress(hDll, "MM_GetMidiInBuffer");
	f_MM_SetMidiInBuffer = (MM_SetMidiInBuffer)GetProcAddress(hDll, "MM_SetMidiInBuffer");
	f_MM_SetRecordProtect = (MM_SetRecordProtect)GetProcAddress(hDll, "MM_SetRecordProtect");
	f_MM_ShowAsioPanel = (MM_ShowAsioPanel)GetProcAddress(hDll, "MM_ShowAsioPanel");
	f_MM_RestartAsioDevice = (MM_RestartAsioDevice)GetProcAddress(hDll, "MM_RestartAsioDevice");
	f_MM_LoadAudio = (MM_LoadAudio)GetProcAddress(hDll, "MM_LoadAudio");
	f_MM_GetMelodyInfo = (MM_GetMelodyInfo)GetProcAddress(hDll, "MM_GetMelodyInfo");
	f_MM_GetMelodyBars = (MM_GetMelodyBars)GetProcAddress(hDll, "MM_GetMelodyBars");
	f_MM_GetMelodyNotes = (MM_GetMelodyNotes)GetProcAddress(hDll, "MM_GetMelodyNotes");
	f_MM_CreateRealTimeMIDIStream = (MM_CreateRealTimeMIDIStream)GetProcAddress(hDll, "MM_CreateRealTimeMIDIStream");
	f_MM_FreeRealTimeMIDIStream = (MM_FreeRealTimeMIDIStream)GetProcAddress(hDll, "MM_FreeRealTimeMIDIStream");
	f_MM_RealTimeMIDINoteOn = (MM_RealTimeMIDINoteOn)GetProcAddress(hDll, "MM_RealTimeMIDINoteOn");
	f_MM_RealTimeMIDINoteOff = (MM_RealTimeMIDINoteOff)GetProcAddress(hDll, "MM_RealTimeMIDINoteOff");
//	f_MM_PlayStyleDemo = (MM_PlayStyleDemo)GetProcAddress(hDll, "MM_PlayStyleDemo");
	f_MM_LoadDemo = (MM_LoadDemo)GetProcAddress(hDll, "MM_LoadDemo");
	f_MM_PlayDemo = (MM_PlayDemo)GetProcAddress(hDll, "MM_PlayDemo");
	f_MM_ChangeDemoParam = (MM_ChangeDemoParam)GetProcAddress(hDll, "MM_ChangeDemoParam");
	f_MM_SetTempo = (MM_SetTempo)GetProcAddress(hDll, "MM_SetTempo");
	f_MM_SetTimeSignature = (MM_SetTimeSignature)GetProcAddress(hDll, "MM_SetTimeSignature");
	f_MM_GetAudioVolume = (MM_GetAudioVolume)GetProcAddress(hDll, "MM_GetAudioVolume");
	f_MM_GetStreamVolume = (MM_GetStreamVolume)GetProcAddress(hDll, "MM_GetStreamVolume");
	f_MM_SetStreamVolume = (MM_SetStreamVolume)GetProcAddress(hDll, "MM_SetStreamVolume");
	f_MM_GetLatency = (MM_GetLatency)GetProcAddress(hDll, "MM_GetLatency");
	f_MM_Save = (MM_Save)GetProcAddress(hDll, "MM_Save");
	f_MM_SaveMidi = (MM_SaveMidi)GetProcAddress(hDll, "MM_SaveMidi");
	f_MM_UserCanceled = (MM_UserCanceled)GetProcAddress(hDll, "MM_UserCanceled");
	f_MM_SaveProject = (MM_SaveProject)GetProcAddress(hDll, "MM_SaveProject");
	f_MM_LoadProject = (MM_LoadProject)GetProcAddress(hDll, "MM_LoadProject");
	f_MM_ResetProject = (MM_ResetProject)GetProcAddress(hDll, "MM_ResetProject");
	f_MM_ActiveAPR = (MM_ActiveAPR)GetProcAddress(hDll, "MM_ActiveAPR");
	f_MM_SetTrackEvent = (MM_SetTrackEvent)GetProcAddress(hDll, "MM_SetTrackEvent");
	f_MM_ShowVSTEditor = (MM_ShowVSTEditor)GetProcAddress(hDll, "MM_ShowVSTEditor");
	f_MM_SaveVSTParams = (MM_SaveVSTParams)GetProcAddress(hDll, "MM_SaveVSTParams");
	f_MM_AudioNewTrack = (MM_AudioNewTrack)GetProcAddress(hDll, "MM_AudioNewTrack");
	f_MM_AudioDeleteTrack = (MM_AudioDeleteTrack)GetProcAddress(hDll, "MM_AudioDeleteTrack");
	f_MM_AudioRecord = (MM_AudioRecord)GetProcAddress(hDll, "MM_AudioRecord");
	f_MM_AudioMove = (MM_AudioMove)GetProcAddress(hDll, "MM_AudioMove");
	f_MM_AudioFx = (MM_AudioFx)GetProcAddress(hDll, "MM_AudioFx");
	f_MM_AudioLoad = (MM_AudioLoad)GetProcAddress(hDll, "MM_AudioLoad");
	f_MM_AudioGetLength = (MM_AudioGetLength)GetProcAddress(hDll, "MM_AudioGetLength");
	f_MM_AddUndoBefore = (MM_AddUndoBefore)GetProcAddress(hDll, "MM_AddUndoBefore");
	f_MM_AddUndoAfter = (MM_AddUndoAfter)GetProcAddress(hDll, "MM_AddUndoAfter");
	f_MM_CancelAddUndo = (MM_CancelAddUndo)GetProcAddress(hDll, "MM_CancelAddUndo");
	f_MM_Undo = (MM_Undo)GetProcAddress(hDll, "MM_Undo");
	f_MM_AudioAddFx = (MM_AudioAddFx)GetProcAddress(hDll, "MM_AudioAddFx");
	f_MM_AudioGetFxParam = (MM_AudioGetFxParam)GetProcAddress(hDll, "MM_AudioGetFxParam");
	f_MM_AudioSetFxParam = (MM_AudioSetFxParam)GetProcAddress(hDll, "MM_AudioSetFxParam");
	f_MM_AudioMoveFx = (MM_AudioMoveFx)GetProcAddress(hDll, "MM_AudioMoveFx");
	f_MM_AudioFxProcess = (MM_AudioFxProcess)GetProcAddress(hDll, "MM_AudioFxProcess");
	f_MM_SetMidiTrackParam = (MM_SetMidiTrackParam)GetProcAddress(hDll, "MM_SetMidiTrackParam");
	f_MM_SetAudioTrackParam = (MM_SetAudioTrackParam)GetProcAddress(hDll, "MM_SetAudioTrackParam");

	if (!(f_MM_InitialObjects && f_MM_DestroyObjects && f_MM_GetFontInfo && f_MM_SetDefaultFont &&
		f_MM_LoadMidiMelody && f_MM_LoadCompose && f_MM_LoadAudio && f_MM_Play && f_MM_GetVersion &&
		f_MM_Stop && f_MM_Save && f_MM_UserCanceled && f_MM_GetMelodyInfo && f_MM_GetVSTInfo &&
		f_MM_CreateRealTimeMIDIStream && f_MM_FreeRealTimeMIDIStream && f_MM_ShowVSTEditor &&
		f_MM_RealTimeMIDINoteOn && f_MM_RealTimeMIDINoteOff && f_MM_SetRecordMoniter &&
		f_MM_SetTempo && f_MM_SetTimeSignature && f_MM_LoadDemo && f_MM_PlayDemo &&
		f_MM_ActiveAPR && f_MM_GetAudioVolume && f_MM_GetStreamVolume && f_MM_SetStreamVolume &&
		f_MM_SaveProject && f_MM_LoadProject && f_MM_GetLatency && f_MM_SetTrackEvent &&
		f_MM_CheckIODevice &&f_MM_SetIODevice && f_MM_GetPlaybackDeviceInfo && f_MM_FreeComposes &&
		f_MM_GetPlaybackOutputInfo && f_MM_GetRecordDeviceInfo && f_MM_GetRecordInputInfo &&
		f_MM_RecordTest && f_MM_SetRecordAutoAdjust && f_MM_SetRecordProtect && f_MM_SaveVSTParams &&
		f_MM_ShowAsioPanel && f_MM_RestartAsioDevice && f_MM_AudioLoad && f_MM_ResetProject &&
		f_MM_GetMidiInBuffer && f_MM_SetMidiInBuffer && f_MM_LoadPrebeat && f_MM_AudioNewTrack &&
		f_MM_AudioDeleteTrack && f_MM_AudioRecord && f_MM_AudioMove && f_MM_AudioFx &&
		f_MM_AddUndoBefore && f_MM_AddUndoAfter && f_MM_CancelAddUndo && f_MM_Undo && f_MM_AudioGetLength &&
		f_MM_AudioAddFx && f_MM_AudioGetFxParam && f_MM_AudioSetFxParam && f_MM_AudioMoveFx && f_MM_AudioFxProcess &&
		f_MM_ChangeDemoParam && f_MM_GetVSTiPrograms && f_MM_LoadVSTi && f_MM_HandleVSTiPreset &&
		f_MM_SetMidiTrackParam && f_MM_SetAudioTrackParam && f_MM_SaveMidi))
	{
		return S_FALSE;
	}

	return S_OK;
}

HRESULT GetCSFunctions(HINSTANCE hDll) {
	// VERIFY( hDll );

	f_CS_GetVersion = (CS_GetVersion)GetProcAddress(hDll, "CS_GetVersion");
	f_CS_InitialService = (CS_InitialService)GetProcAddress(hDll,"CS_InitialService");
	f_CS_DestroyService = (CS_DestroyService)GetProcAddress(hDll,"CS_DestroyService");
	f_CS_Register = (CS_Register)GetProcAddress(hDll, "CS_Register");
	f_CS_Login = (CS_Login)GetProcAddress(hDll, "CS_Login");
	f_CS_Logoff = (CS_Logoff)GetProcAddress(hDll, "CS_Logoff");
	f_CS_CheckPayment = (CS_CheckPayment)GetProcAddress(hDll, "CS_CheckPayment");
	f_CS_ConfirmPayment = (CS_ConfirmPayment)GetProcAddress(hDll, "CS_ConfirmPayment");
	f_CS_CancelOperation = (CS_CancelOperation)GetProcAddress(hDll,	"CS_CancelOperation");
	f_CS_DownloadStyle = (CS_DownloadStyle)GetProcAddress(hDll,	"CS_DownloadStyle");
	f_CS_GetQnA = (CS_GetQnA)GetProcAddress(hDll, "CS_GetQnA");
	f_CS_SubmitQnA = (CS_SubmitQnA)GetProcAddress(hDll, "CS_SubmitQnA");
	f_CS_GetNotice = (CS_GetNotice)GetProcAddress(hDll, "CS_GetNotice");
	f_CS_GetNewNoticeNum = (CS_GetNewNoticeNum)GetProcAddress(hDll, "CS_GetNewNoticeNum");
	f_CS_UploadSong = (CS_UploadSong)GetProcAddress(hDll, "CS_UploadSong");
	f_CS_GetWebPageURL = (CS_GetWebPageURL)GetProcAddress(hDll, "CS_GetWebPageURL");
	f_CS_GetStyleNumsEx = (CS_GetStyleNumsEx)GetProcAddress(hDll, "CS_GetStyleNumsEx");
	f_CS_StyleScore = (CS_StyleScore)GetProcAddress(hDll, "CS_StyleScore");
	f_CS_AutoDownloadStyle = (CS_AutoDownloadStyle)GetProcAddress(hDll, "CS_AutoDownloadStyle");
	f_CS_SaveProject = (CS_SaveProject)GetProcAddress(hDll, "CS_SaveProject");
	f_CS_LoadProject = (CS_LoadProject)GetProcAddress(hDll, "CS_LoadProject");
	f_CS_ResetProject = (CS_ResetProject)GetProcAddress(hDll, "CS_ResetProject");
	f_CS_UploadStyle = (CS_UploadStyle)GetProcAddress(hDll, "CS_UploadStyle");

	if (!(f_CS_InitialService && f_CS_DestroyService && f_CS_Login && f_CS_Login
			&& f_CS_CheckPayment && f_CS_ConfirmPayment && f_CS_CancelOperation
			&& f_CS_GetQnA && f_CS_SubmitQnA && f_CS_Register && f_CS_UploadSong
			&& f_CS_GetWebPageURL && f_CS_GetStyleNumsEx && f_CS_GetNotice
			&& f_CS_DownloadStyle && f_CS_GetNewNoticeNum && f_CS_StyleScore
			&& f_CS_AutoDownloadStyle && f_CS_SaveProject && f_CS_LoadProject
			&& f_CS_ResetProject && f_CS_UploadStyle && f_CS_GetVersion)) {
		return S_FALSE;
	}

	return S_OK;
}

HRESULT GetQRFunctions(HINSTANCE hDll) {
	f_QR_Encode = (QR_Encode)GetProcAddress(hDll, "QR_Encode");

	return S_OK;
}

void SetMelodyTempo(int nTempo, bool bInit) {
	if (bInit || g_nMelodyTempo != nTempo) {
		g_dblTimePerBar = (double)g_nBPM * 60000.0 / nTempo;
		g_dblStep = TIMER_PLAY_INTERVAL * POINTS_PER_BAR / g_dblTimePerBar;//* (double)nTempo / g_nBPM / 60000.0;

		f_MM_SetTempo(nTempo);
		g_nMelodyTempo = nTempo;

		f_CS_ResetProject();
		g_bProjStylePaid = false;

		if( g_aAudioTracks.size()>1 ){
			ClearGlobalVars( LIST_OPUSAUDIOS );
		}

		if( !g_Theme.Empty() ){
			ClearGlobalVars( LIST_RAWAUDIO );
			g_bPredefine = true;
		}

		ClearGlobalVars( LIST_UNDO );
	}
}

void SetMelodyTS(int iTS, bool bInit)
{
	if (bInit || g_iMelodyTimeSignature != iTS) {
		g_nBPM = iTS==0 ? 4 : ( iTS==2 ? 2 : 3 );
		g_nPPB = POINTS_PER_BAR / g_nBPM;
		if( iTS==3 ) g_nPPB /= 2;

		g_dblTimePerBar = (double)g_nBPM * 60000.0 / g_nMelodyTempo;
		g_dblStep = TIMER_PLAY_INTERVAL * POINTS_PER_BAR / g_dblTimePerBar;//* (double)g_nMelodyTempo / (double)g_nBPM / 60000.0;
		g_nChordNumPerBar = iTS==0 ? 4 : ( iTS==1 ? 3 : 2 );

		f_MM_SetTimeSignature( iTS );
		g_iMelodyTimeSignature = iTS;
	}
}

int ActiveAPR( bool bActive )
{
	if( f_MM_ActiveAPR ){
		return f_MM_ActiveAPR( bActive );
	}

	return S_FALSE;
}

void SetMelodyNotes( int nBarNum ) {
	int nNotesNum = f_MM_GetMelodyNotes( NULL, NULL, &g_iMelodyKey );//f_MM_GetMelodyInfo(NULL, NULL, NULL);
	if( nNotesNum>0 ) {
		BYTE *aNotes = new BYTE[nNotesNum];
		WORD *aTicks = new WORD[nNotesNum];

		f_MM_GetMelodyNotes( aNotes, aTicks, NULL );
		//f_MM_GetMelody( aNotes, aTicks, g_iMelodyKey );

 //		//(g_nMelodyTempo >= 125) ? 24 : (g_nMelodyTempo >= 83) ? 48 : 72;

		DebugPrint("CM_SetMelodyNotes");
		f_CM_SetMelodyNotes(nNotesNum, aNotes, aTicks, 192,
						(BYTE)g_iMelodyTimeSignature, g_nMelodyTempo );

		// 计算弱起
		g_bWeakup = nBarNum>1 && aNotes[0] == 128 && aTicks[0]>192 * g_nBPM / 2;

		delete[]aNotes;
		delete[]aTicks;
	}
}

void SetPlayTimer(bool bStart, UINT& tTimer, UINT& tAccuracy, void* pUser, int tInterval) {
	if (bStart) { // 打开定时器
		// 设置定时器
		TIMECAPS tc;
		MMRESULT mrError;

		// 利用函数timeGetDevCaps取出系统分辨率的取值范围，如果有错报错退出
		memset(&tc, 0, sizeof(TIMECAPS));
		mrError = timeGetDevCaps(&tc, sizeof(TIMECAPS));
		if (!mrError == TIMERR_NOERROR) {
			DebugPrint("Get system accuracy failed! code = %x", mrError);
		}

		// 分辨率的值不能超出系统的取值范围
		tAccuracy = tc.wPeriodMin > TIMER_ACCURACY ? tc.wPeriodMin : TIMER_ACCURACY;
		tAccuracy = tAccuracy < tc.wPeriodMax ? tAccuracy : tc.wPeriodMax;

		// 调用timeBeginPeriod函数设置定时器的分辨率
		timeBeginPeriod(tAccuracy);

		tTimer = timeSetEvent(tInterval, tAccuracy,
			(LPTIMECALLBACK)OnMediaTimer, (DWORD_PTR)pUser, TIME_PERIODIC);

	}
	else { // 关闭定时器
		timeKillEvent(tTimer);
		timeEndPeriod(tAccuracy);
		tTimer = 0;
	}
}

void GetPlayTime(int iStartBar, double dblStartPoint, int iTime[3] )
{
	if (g_bShowPlayTick) {
		int iBeat = dblStartPoint / g_nPPB,
			iTick =	120 * (dblStartPoint - iBeat * g_nPPB) / g_nPPB;
		iTime[0] = iStartBar + 1;
		iTime[1] = iBeat + 1;
		iTime[2] = iTick;
	}
	else {
		UINT tStartTime = (INT)((iStartBar + dblStartPoint / POINTS_PER_BAR)
											* (double)g_nBPM * 60000.0 / g_nMelodyTempo);
		iTime[0] = tStartTime / 60000;
		iTime[1] = (tStartTime % 60000) / 1000;
		iTime[2] = tStartTime % 1000;
	}
}

void CALLBACK OnMediaTimer(UINT tTimerID, UINT msg, DWORD dwUser, DWORD dwl, DWORD dw2) {
	PostMessage((HWND)dwUser, MSG_MEDIATIME, tTimerID, 0);
}

void InitCZFontList( String strPath )
{
	UnicodeString strWildcard[2] = { L"\\ext\\*.", L"\\ext\\*.sf2" };

	TSearchRec sr;
	int iAttr = 0;
	int nInst, nDrum;
	FONTPRESET setInst[128], setDrum[128];

	for( int w=0; w<2; w++ ){
		if (FindFirst(strPath + strWildcard[w], iAttr, sr) == 0) {
			do {
				AnsiString strFileName = strPath + "\\ext\\" + sr.Name;
				char strFontName[80] = "";

				if( f_MM_GetFontInfo(strFileName.c_str(), strFontName, &nInst, setInst,
															&nDrum, setDrum )==S_OK ){
					SetCZFonts( strFileName.c_str(), strFontName, nInst, setInst,
																nDrum, setDrum );
				}
			}
			while( FindNext(sr)==0 );

			FindClose(sr);
		}
		else {
			iAttr = GetLastError();
		}
	}
}

void InitFontList()
{
	UnicodeString strPath = g_strExecutePath.c_str(),
		strFontPath = L"Fonts",
		strWildcard[2] = { L"\\*.", L"\\*.sf2" };//, L"\\*.sfz" };

	strPath += strFontPath;

	//扫描扩展音色库
	memset( g_lstCZFonts, 0, sizeof(g_lstCZFonts) );

	if( !g_strExtFontsPath.empty() ){
		UnicodeString strExtFontPath = g_strExtFontsPath.c_str();

		if( strExtFontPath.CompareIC( strPath ) )
			InitCZFontList( strExtFontPath );
	}

	InitCZFontList( strPath );

	g_bExtFontUsable = true;
	for( int i=0; i<18; i++ ){
		if( g_lstCZFonts[i]!=NULL ){
        	g_lstFonts.push_back( g_lstCZFonts[i] );
		}
		else if( i<17 ){
			g_bExtFontUsable = false;
            break;
		}
	}

	// 扫描GM音色库
	TSearchRec sr;
	int iAttr = 0;
	int nInst, nDrum;
	FONTPRESET setInst[128], setDrum[128];

	for( int w=0; w<2 && g_lstFonts.size()<MAX_FONTS_NUM; w++ ){
		if (FindFirst(strPath + strWildcard[w], iAttr, sr) == 0) {
			do {
				AnsiString strFileName = strPath + "\\" + sr.Name;
				char strFontName[80] = "";

				if( f_MM_GetFontInfo(strFileName.c_str(), strFontName, &nInst, setInst,
														&nDrum, setDrum )==S_OK ){
					bool bAdd = true;
					int iInsert = -1;

					for( int j=0; j<g_lstFonts.size(); j++ ){
						FONTINFO* pF = g_lstFonts[j];

						int iComp = StrComp( strFontName, pF->strFontName );

						if( iComp < 0 ){
							iInsert = j;
							break;
						}
						else if( iComp==0 ){
							bAdd = false;
							break;
						}
					}

					if( bAdd ){
						FONTINFO * pNewFI = new FONTINFO( strFileName.c_str(), strFontName,
															nInst, setInst, nDrum, setDrum );
						if( iInsert<0 ){
							g_lstFonts.push_back(pNewFI);
						}
						else{
							g_lstFonts.insert( g_lstFonts.begin()+iInsert, pNewFI );
						}
					}
				}
			}
			while( FindNext(sr)==0 && g_lstFonts.size()<MAX_FONTS_NUM );

			FindClose(sr);
		}
		else {
			iAttr = GetLastError();
		}
	}
}
// ---------------------------------------------------------------------------

bool SetCZFonts( char* szFileName, char* szFontName, int nInst, FONTPRESET* setInst,
													int nDrum, FONTPRESET* setDrum )
{
	for( int i=0; i<18; i++ ){
		if( !StrComp( szFontName, g_strCZFont[i] ) ){
			if( g_lstCZFonts[i]==NULL )
				g_lstCZFonts[i] = new FONTINFO( szFileName, szFontName, nInst, setInst,
																nDrum, setDrum );

			return true;
		}
	}

	return false;
}
// ---------------------------------------------------------------------------

bool SetSelectFont()
{
	bool bLastFontFound = false;
	int idDefaultFont = -1, idFirstGM = -1;
	for( int i = 0; i < g_lstFonts.size(); i++ ){
		FONTINFO * pFI = g_lstFonts[i];

		if( strcmp( pFI->strFontName, g_strSoundFont )==0 ){
			bLastFontFound = true;
			g_idFont = i;
			break;
		}

		if( idDefaultFont<0 && strcmp( pFI->strFontName, g_strDefaultSoundSet )==0 ){
			idDefaultFont = i;
		}

		if( idDefaultFont<0 && idFirstGM<0 && pFI->nInstCount>0 && pFI->nDrumCount>0 ){
			idFirstGM = i;
		}
	}

	if( !bLastFontFound ){
		if( idDefaultFont!=-1 ) {
			g_idFont = idDefaultFont;
		}
		else if( idFirstGM ){
			g_idFont = idFirstGM;
		}
		else{
			g_idFont = 0;
        }
	}

	strcpy( g_strSoundFont, g_lstFonts[g_idFont]->strFontName );

	if( g_bExtFont ){
		if( !g_bExtFontUsable ){
			g_bExtFont = false;
			bLastFontFound = false;
		}
		else
            bLastFontFound = true;
	}

	char aFiles[17][256];
	int num = 0;
	if( g_bExtFont ){
		for( int i=0; i<17; i++ ){
			strcpy( aFiles[i], g_lstCZFonts[i]->strFileName );
		}
		num = 17;
	}
	else{
		num = 1;
		strcpy( aFiles[0], g_lstFonts[g_idFont]->strFileName );
	}

	f_MM_SetDefaultFont( num, aFiles );

	return bLastFontFound;
}
// ---------------------------------------------------------------------------

void ClearFontList()
{
/*	for( int i=0; i<18; i++ ){
		if( g_lstCZFonts[i]!=NULL )
			delete g_lstCZFonts[i];
	}
*/
	FONTINFOLIST::iterator iFI = g_lstFonts.begin();
	while( iFI != g_lstFonts.end() ){
		FONTINFO* pF = *iFI;

		if( pF->nInstCount>0 )
			delete[] pF->aInsts;
		if( pF->nDrumCount>0 )
			delete[] pF->aDrums;

		delete pF;
		iFI = g_lstFonts.erase(iFI);
	}
}
// ---------------------------------------------------------------------------
#define MAX_VST_PLUGINS 1024
#include "SplashFormUnit.h"
void InitVSTList()
{
	String strVSTPath, strVSTiPath;
	int rpt = 0;

	if( !g_strVSTPath.empty() ){
		strVSTPath = g_strVSTPath.c_str();
		rpt++;
	}

	if( !g_strVSTiPath.empty() ){
		strVSTiPath = g_strVSTiPath.c_str();

		if( strVSTPath.CompareIC( strVSTiPath ) )
			rpt++;
	}

	for( int r=0; r<rpt; r++ ){
		TSearchRec sr;
		int iAttr = 0;
		String& strPath = (r==0 && strVSTPath.Length()>0) ? strVSTPath : strVSTiPath;
		strPath += "\\";

		if( strPath==strVSTPath )
			SetVSTScanReg( 1 );
		else
			SetVSTScanReg( 2 );

		AnsiString strFileName = strPath.c_str();
		strFileName += L"*.dll";

		if (FindFirst(strFileName, iAttr, sr) == 0) {
			do {
				char strEffName[32] = "",
					strPlugins[MAX_VST_PLUGINS][64];
				DWORD uniqueID = 0;
				UINT idPlugins[MAX_VST_PLUGINS];
				int nPlugins = MAX_VST_PLUGINS;

				strFileName = strPath.c_str() + sr.Name;

				if( SplashForm ){
					String strMsg = "扫描VST插件: " + sr.Name;
					SplashForm->ShowProgress( strMsg );
				}

				int ret = f_MM_GetVSTInfo( strFileName.c_str(), strEffName, uniqueID,
													nPlugins, strPlugins, idPlugins );

				if( ret>0 ){
					VSTINFOLIST& lstVST = (ret & VSTeffect) ? g_lstVSTFx : g_lstVSTi;
					bool bAdd = true;

					for( int i=0; i<lstVST.size(); i++ ){
						VSTINFO* pVI = lstVST[i];
						if( pVI->uniqueID==uniqueID ){
							bAdd = false;
							break;
						}
					}

					if( bAdd && lstVST.size()<MAX_VST_PLUGINS ){
						VSTINFO * pVI = new VSTINFO( strFileName.c_str(), strEffName, uniqueID );
						lstVST.push_back( pVI );

						for( int i=0; i<nPlugins; i++ ){
							VSTPLUGIN* pPlugin = new VSTPLUGIN;
							pPlugin->id = idPlugins[i];
							strcpy( pPlugin->name, strPlugins[i] );
							pVI->aPlugins.push_back( pPlugin );
						}
					}
				}
			}
			while( FindNext(sr)==0 );

			FindClose(sr);
		}
		else {
			iAttr = GetLastError();
		}
	}

	SetVSTScanReg( 0 );
}
// ---------------------------------------------------------------------------

void ClearVSTList()
{
	while( !g_lstVSTFx.empty() ){
		delete g_lstVSTFx.back();
		g_lstVSTFx.pop_back();
	}

	while( !g_lstVSTi.empty() ){
		delete g_lstVSTi.back();
		g_lstVSTi.pop_back();
	}
}
// ---------------------------------------------------------------------------

void SelectStyle()
{
	ClearStyleList();
	g_pPreStyle = NULL;

	//获取收藏列表
	int nCollects = 0;
	UINT (*idCollects)[2] = NULL;
	f_CM_GetCollectionIDs( g_iMelodyTimeSignature, nCollects, NULL );
	if( nCollects>0 ){
		idCollects = new UINT[nCollects][2];
		f_CM_GetCollectionIDs( g_iMelodyTimeSignature, nCollects, idCollects );
	}

	//获取推荐列表
	int nRecomNum = 50;
	DWORD idRecoms[50];

	f_CM_GetStyleRecomIDs( g_iMelodyTimeSignature, idRecoms, &nRecomNum );

	//获取当前节拍所有风格
	int nStyleNum = 0;
	TPROSTYLE * aStyleInfos = NULL;

	if( 0==f_CM_GetStyleInfos( e_ST_Origin, g_iMelodyTimeSignature, NULL, &nStyleNum )
																	&& nStyleNum>0 ){
		aStyleInfos = new TPROSTYLE[nStyleNum];
		for( int i=0; i<nStyleNum; i++ ){
			aStyleInfos[i].pOrigin = new TSTYLEORIGIN;
		}

		f_CM_GetStyleInfos( e_ST_Origin, g_iMelodyTimeSignature, aStyleInfos, &nStyleNum );

		for( int i=0; i<nStyleNum; i++ ){
			TPROSTYLE* pInfo = new TPROSTYLE;
			memcpy( pInfo, &aStyleInfos[i], sizeof(TPROSTYLE) );

			pInfo->pOrigin = new TSTYLEORIGIN;
			memcpy( pInfo->pOrigin, aStyleInfos[i].pOrigin, sizeof(TSTYLEORIGIN) );

			g_aOriginStyles.push_back( pInfo );

			for( int j=0; j<nCollects; j++ ){
				if( idCollects[j][0]==pInfo->idLoc && idCollects[j][1]==pInfo->idStyle ){
					g_aCollectStyles.push_back( pInfo );
					break;
				}
			}

			for( int j=0; j<nRecomNum; j++ ){
				if(  idRecoms[j]==pInfo->idStyle ){
					g_aRecomStyles.push_back( pInfo );
					break;
				}
			}
		}

		delete[] aStyleInfos;

		if( 0==f_CM_GetStyleInfos( e_ST_Share, g_iMelodyTimeSignature, NULL, &nStyleNum )
																	&& nStyleNum>0 ){
			aStyleInfos = new TPROSTYLE[nStyleNum];
			for( int i=0; i<nStyleNum; i++ ){
				aStyleInfos[i].pShare = new TSTYLESHARE;
			}

			f_CM_GetStyleInfos( e_ST_Share, g_iMelodyTimeSignature, aStyleInfos, &nStyleNum );

			for( int i=0; i<nStyleNum; i++ ){
				TPROSTYLE* pInfo = new TPROSTYLE;
				memcpy( pInfo, &aStyleInfos[i], sizeof(TPROSTYLE) );

				pInfo->pShare = new TSTYLESHARE;
				memcpy( pInfo->pShare, aStyleInfos[i].pLocal, sizeof(TSTYLESHARE) );

				g_aShareStyles.push_back( pInfo );

				for( int j=0; j<nCollects; j++ ){
					if( idCollects[j][0]==pInfo->idLoc && idCollects[j][1]==pInfo->idStyle ){
						g_aCollectStyles.push_back( pInfo );
						break;
					}
				}
			}

			delete[] aStyleInfos;
		}

		if( 0==f_CM_GetStyleInfos( e_ST_Temp, g_iMelodyTimeSignature, NULL, &nStyleNum )
																	&& nStyleNum>0 ){
			aStyleInfos = new TPROSTYLE[nStyleNum];
			for( int i=0; i<nStyleNum; i++ ){
				aStyleInfos[i].pLocal = new TSTYLELOCAL;
			}

			f_CM_GetStyleInfos( e_ST_Temp, g_iMelodyTimeSignature, aStyleInfos, &nStyleNum );

			for( int i=0; i<nStyleNum; i++ ){
				TPROSTYLE* pInfo = new TPROSTYLE;
				memcpy( pInfo, &aStyleInfos[i], sizeof(TPROSTYLE) );

				pInfo->pLocal = new TSTYLELOCAL;
				memcpy( pInfo->pLocal, aStyleInfos[i].pLocal, sizeof(TSTYLELOCAL) );

				g_aLocalStyles.push_back( pInfo );

				for( int j=0; j<nCollects; j++ ){
					if( idCollects[j][0]==pInfo->idLoc && idCollects[j][1]==pInfo->idStyle ){
						g_aCollectStyles.push_back( pInfo );
						break;
					}
				}
			}

			delete[] aStyleInfos;
		}
	}
	else{
		DebugPrint("获取风格失败");
	}

	if( idCollects )
		delete[] idCollects;
}

void ClearStyleList()
{
	for( int i=0; i<g_aOriginStyles.size(); i++ ){
		delete g_aOriginStyles[i];
	}
	g_aOriginStyles.clear();

	for( int i=0; i<g_aShareStyles.size(); i++ ){
		delete g_aShareStyles[i];
	}
	g_aShareStyles.clear();

	for( int i=0; i<g_aLocalStyles.size(); i++ ){
		delete g_aLocalStyles[i];
	}
	g_aLocalStyles.clear();

	for( int i=0; i<g_aTempStyles.size(); i++ ){
		delete g_aTempStyles[i];
	}
	g_aTempStyles.clear();

	g_aCollectStyles.clear();
	g_aRecomStyles.clear();
	u_aCacheStyles.clear();

	ClearStyleMap();
	ClearProjStyleMap();
}

void ClearStyleMap()
{
	for( int i=g_aTempStyles.size()-1; i>=0; i-- ){
		if( g_aTempStyles[i]->idStyle!=0 ){
			f_CM_DeleteTempStyle( g_aTempStyles[i]->idStyle );
			delete g_aTempStyles[i];
			g_aTempStyles.erase( g_aTempStyles.begin() + i );
		}
	}
}

TPROSTYLE* GetStyleInfo( UINT idLoc, UINT idStyle )
{
	if( idLoc==0 && idStyle==0 )
		return NULL;

	for( int i=u_aCacheStyles.size()-1; i>=0; i-- ){
		if( u_aCacheStyles[i]->idLoc==idLoc && u_aCacheStyles[i]->idStyle==idStyle ){
			return u_aCacheStyles[i];
		}
	}

	TPROSTYLE* pStyle = NULL;
	if( idLoc==0 ){
		for( int i=0; i<g_aOriginStyles.size(); i++ ){
			if( g_aOriginStyles[i]->idStyle==idStyle ){
				pStyle = g_aOriginStyles[i];
				break;
			}
		}
	}
	else if( idLoc==1 ){
		for( int i=0; i<g_aShareStyles.size(); i++ ){
			if( g_aShareStyles[i]->idStyle==idStyle ){
				pStyle = g_aShareStyles[i];
				break;
			}
		}
	}
	else if( idLoc==(UINT)-1 ){
		for( int i=0; i<g_aTempStyles.size(); i++ ){
			if( g_aTempStyles[i]->idStyle==idStyle ){
				pStyle = g_aTempStyles[i];
				break;
			}
		}
	}
	else{
		for( int i=0; i<g_aLocalStyles.size(); i++ ){
			if( g_aLocalStyles[i]->idLoc==idLoc
						&& g_aLocalStyles[i]->idStyle==idStyle ){
				pStyle = g_aLocalStyles[i];
				break;
			}
		}
	}

	if( pStyle ){
		u_aCacheStyles.push_back( pStyle );
		if( u_aCacheStyles.size()>MAX_STYLE_CACHE ){
			u_aCacheStyles.erase( u_aCacheStyles.begin() );
		}
	}

	return pStyle;
}

bool IsCollectedStyle( UINT idLoc, UINT idStyle )
{
	for( int i=0; i<g_aCollectStyles.size(); i++ ){
		if( g_aCollectStyles[i]->idLoc==idLoc && g_aCollectStyles[i]->idStyle==idStyle ){
			return true;
		}
	}

	return false;
}

void DeleteStyleInfo( UINT idLoc, UINT idStyle )
{
	if( idLoc==0 && idStyle==0 )
		return;

	for( int i=0; i<u_aCacheStyles.size(); i++ ){
		if( u_aCacheStyles[i]->idLoc==idLoc && u_aCacheStyles[i]->idStyle==idStyle ){
			u_aCacheStyles.erase( u_aCacheStyles.begin()+i );
			break;
		}
	}

	for( int i=0; i<g_aCollectStyles.size(); i++ ){
		if( g_aCollectStyles[i]->idLoc==idLoc && g_aCollectStyles[i]->idStyle==idStyle ){
			g_aCollectStyles.erase( g_aCollectStyles.begin()+i );
			break;
		}
	}

	if( idLoc==0 ){
		for( int i=0; i<g_aOriginStyles.size(); i++ ){
			if( g_aOriginStyles[i]->idStyle==idStyle ){
				delete g_aOriginStyles[i];
				g_aOriginStyles.erase( g_aOriginStyles.begin()+i );
				break;
			}
		}
	}
	else if( idLoc==1 ){
		for( int i=0; i<g_aShareStyles.size(); i++ ){
			if( g_aShareStyles[i]->idStyle==idStyle ){
				delete g_aShareStyles[i];
				g_aShareStyles.erase( g_aShareStyles.begin()+i );
				break;
			}
		}
	}
	else if( idLoc==(UINT)-1 ){
		for( int i=0; i<g_aTempStyles.size(); i++ ){
			if( g_aTempStyles[i]->idStyle==idStyle ){
				delete g_aTempStyles[i];
				g_aTempStyles.erase( g_aTempStyles.begin()+i );
				break;
			}
		}
	}
	else{
		for( int i=g_aLocalStyles.size()-1; i>=0; i-- ){
			if( g_aLocalStyles[i]->idLoc==idLoc
						&& g_aLocalStyles[i]->idStyle==idStyle ){
				delete g_aLocalStyles[i];
				g_aLocalStyles.erase( g_aLocalStyles.begin()+i );
			}
			else{
				int ret = DeleteTrkRef( *g_aLocalStyles[i]->pLocal, idLoc, idStyle );
				if( ret==-1 ){
					for( int j=0; j<u_aCacheStyles.size(); j++ ){
						if( u_aCacheStyles[j]->idLoc==g_aLocalStyles[i]->idLoc
									&& u_aCacheStyles[j]->idStyle==g_aLocalStyles[i]->idStyle ){
							u_aCacheStyles.erase( u_aCacheStyles.begin()+j );
							break;
						}
					}

					delete g_aLocalStyles[i];
					g_aLocalStyles.erase( g_aLocalStyles.begin()+i );
				}
			}
		}
	}
}

int DeleteTrkRef( TSTYLELOCAL& origin, UINT idLocDel, UINT idStyleDel )
{
	int ret = 0;

	bool bChanged = false;
	for( int s=0; s<4; s++ ){
		int rep = s<2 ? 1 : 2;
		for( int r=0; r<rep; r++ ){
			int nSegNum = origin.nSegNum[s];
			int iStart = r * 4,
				iEnd = iStart + ( r==0 ? ( nSegNum & 0x0F ) : ( nSegNum>>4 ));

			for( int n=iStart; n<iEnd; n++ ){
				for( int t=0; t<16; t++ ){
					if( origin.trkRef[s][n][t].idLoc==idLocDel
									&& origin.trkRef[s][n][t].idStyle==idStyleDel ){
						origin.trkRef[s][n][t].idLoc = 0;
						origin.trkRef[s][n][t].idStyle = 0;

						if( !bChanged ){
							bChanged = true;
							ret = -1;
						}
					}
				}
			}
		}
	}

	if( bChanged ){
		TSTYLELOCAL update;

		for( int s=0; s<4; s++ ){
			int rep = s<2 ? 1 : 2;
			for( int r=0; r<rep; r++ ){
				int nSegNum = origin.nSegNum[s];
				int iStart = r * 4,
					iEnd = iStart + ( r==0 ? ( nSegNum & 0x0F ) : ( nSegNum>>4 ));

				int segCount = 0;
				for( int n=iStart; n<iEnd; n++ ){
					int trkCount = 0;
					for( int t=0; t<16; t++ ){
						if( origin.trkRef[s][n][t].idLoc!=0
										|| origin.trkRef[s][n][t].idStyle!=0 ){
							memcpy( &update.trkRef[s][iStart+segCount][trkCount],
											&origin.trkRef[s][n][t], sizeof(TTRACKREF) );
							trkCount++;
						}
					}

					if( trkCount>0 ){
						if( s>=2 )
							update.aIEBars[s-2][iStart+segCount] = origin.aIEBars[s-2][n];

						segCount++;
					}
				}

				if( segCount>0 ){
					if( r==0 )
						update.nSegNum[s] += segCount;
					else
						update.nSegNum[s] += (segCount<<4);

					if( ret==-1 )
						ret = 1;
				}
			}
		}

		if( ret==1 ){
			memcpy( &origin.trkRef, &update.trkRef, sizeof(TTRACKREF)*4*8*16 );
			memcpy( &origin.nSegNum, &update.nSegNum, sizeof(char)*4 );
			memcpy( &origin.aIEBars, &update.aIEBars, sizeof(char)*2*8 );
		}
	}

	return ret;
}

void ClearGlobalVars(int iOperation) {
//	g_bSongSaved = false;

	if( iOperation & LIST_OPUSSTAGES ){
		g_Midi.ClearMidiTracks();

		while( g_lstOpusStages.size()>0 ){
			delete g_lstOpusStages.back();
			g_lstOpusStages.pop_back();
		}

		g_Opus.Backup();
	}

	if( iOperation & LIST_OPUSAUDIOS ){
		for( int i=g_aAudioTracks.size()-1; i>0; i-- ){
			f_MM_AudioDeleteTrack( i );
			delete g_aAudioTracks.back();
			g_aAudioTracks.pop_back();
		}
	}

	if( iOperation & LIST_RAWAUDIO ){
		f_MM_AudioDeleteTrack( 0 );
		delete g_aAudioTracks[0];
		g_aAudioTracks[0] = new TAudioTrack;
	}

	if( iOperation & LIST_THEME ){
		g_Theme.Clear();
	}

	if( iOperation & LIST_UNDO ){
		g_Undo.ClearUndoList();
	}
}



#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <time.h>

#define MAX_DEBUG_PRINT 10240

string wstr2str(const wstring& _src) {
	int nBufSize = WideCharToMultiByte(GetACP(), 0, _src.c_str(), -1, NULL, 0,
		0, FALSE);

	char *szBuf = new char[nBufSize];

	WideCharToMultiByte(GetACP(), 0, _src.c_str(), -1, szBuf, nBufSize,
		0, FALSE);

	string strRet(szBuf);

	delete[]szBuf;

	return strRet;
}

wstring str2wstr(const string& _src) {
	int nBufSize = MultiByteToWideChar(GetACP(), 0, _src.c_str(), -1, NULL, 0);

	wchar_t *wsBuf = new wchar_t[nBufSize];

	MultiByteToWideChar(GetACP(), 0, _src.c_str(), -1, wsBuf, nBufSize);

	wstring wstrRet(wsBuf);

	delete[]wsBuf;

	return wstrRet;
}

string UTF8ToMBCS(const char *pcUtf8) {

	// wchar_t pcUnicode[CHAR_BUFSIZE];

	int nUnicodeLen = MultiByteToWideChar(CP_UTF8, 0, pcUtf8, -1, NULL, 0);

	wchar_t * pcUnicode = new wchar_t[nUnicodeLen + 1];
	memset(pcUnicode, 0, nUnicodeLen * 2 + 2);

	// utf8 to unicode

	MultiByteToWideChar(CP_UTF8, 0, pcUtf8, -1, pcUnicode, nUnicodeLen);

	// unicode to gb2312

	int nMBCSLen = WideCharToMultiByte(CP_ACP, 0, pcUnicode, -1, NULL, 0,
		NULL, NULL);

	char *pcMBCS = new char[nMBCSLen + 1];
	memset(pcMBCS, 0, nMBCSLen + 1);

	WideCharToMultiByte(CP_ACP, 0, pcUnicode, -1, pcMBCS, nMBCSLen, NULL, NULL);

	string strMBCS = pcMBCS;
	delete[]pcMBCS;
	delete[]pcUnicode;

	return strMBCS;
}

string GBToUTF8(const char* str)
{
     string result;
     WCHAR *strSrc;
	 char *szRes;

	 //获得临时变量的大小
     int i = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
     strSrc = new WCHAR[i+1];
     MultiByteToWideChar(CP_ACP, 0, str, -1, strSrc, i);

     //获得临时变量的大小
     i = WideCharToMultiByte(CP_UTF8, 0, strSrc, -1, NULL, 0, NULL, NULL);
	 szRes = new char[i+1];
	 i = WideCharToMultiByte(CP_UTF8, 0, strSrc,-1, szRes, i, NULL, NULL);

     result = szRes;
     delete []strSrc;
     delete []szRes;

     return result;
}

void DebugPrint(const char * fmt, ...) {
#ifdef _DEBUG
	char sDebug[MAX_DEBUG_PRINT];
	sDebug[0] = '\0';

	char tbuffer[9];
	_strtime(tbuffer);

	sprintf(sDebug, "[%s] ", tbuffer);

	va_list vaParams;
	va_start(vaParams, fmt);

	vsprintf(sDebug + strlen(sDebug), fmt, vaParams);
	OutputDebugStringA(sDebug);
#endif
}

void SetInitVar(BOOL bClose) {
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;
	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, (TCHAR*)REGKEY_SOFTWARE, 0,
		NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		if (bClose) {
			DWORD dwValue = TRUE;
			lResult = RegSetValueEx(hComposerKey, L"NormalClosed", 0, REG_DWORD,
				(LPBYTE) & dwValue, sizeof(DWORD));
		}
		if( strlen(g_strSoundFont)>0 )
			lResult = RegSetValueEx(hComposerKey, L"FontName", 0, REG_SZ,
				(LPBYTE)g_strSoundFont, strlen(g_strSoundFont)+1 );

		lResult = RegSetValueEx(hComposerKey, L"TimeSignature", 0, REG_DWORD,
			(LPBYTE) &g_iMelodyTimeSignature, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"Tempo", 0, REG_DWORD,
			(LPBYTE) &g_nMelodyTempo, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"PlaybackDevice", 0, REG_DWORD,
			(LPBYTE) &g_iPlaybackDevice, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"PlaybackOutput", 0, REG_DWORD,
			(LPBYTE) &g_iPlaybackOutput, sizeof(DWORD));
		if( strlen(g_strPlaybackDevice)>0 )
			lResult = RegSetValueEx(hComposerKey, L"PlaybackDeviceName", 0, REG_SZ,
				(LPBYTE)g_strPlaybackDevice, strlen(g_strPlaybackDevice)+1);
		lResult = RegSetValueEx(hComposerKey, L"RecordDevice", 0, REG_DWORD,
			(LPBYTE) &g_iRecordDevice, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"RecordInput", 0, REG_DWORD,
			(LPBYTE) &g_iRecordInput, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"RecordDeviceName", 0, REG_SZ,
			(LPBYTE)g_strRecordDevice, strlen(g_strRecordDevice)+1);
		lResult = RegSetValueEx(hComposerKey, L"RecordAutoAdjust", 0, REG_DWORD,
			(LPBYTE) &g_bRecordAutoAdjust, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"RecordVolume", 0, REG_BINARY,
			(LPBYTE) &g_fRecordVolume, sizeof(float));
		lResult = RegSetValueEx(hComposerKey, L"SpeakerVolume", 0, REG_BINARY,
			(LPBYTE) &g_fSpeakerVolume, sizeof(float));
		lResult = RegSetValueEx(hComposerKey, L"LastSaveOption2", 0, REG_DWORD,
			(LPBYTE) &g_iLastSaveOption, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"WindowState", 0, REG_DWORD,
			(LPBYTE) &g_iWindowState, sizeof(DWORD));
		lResult = RegSetValueEx(hComposerKey, L"LastSaveType", 0, REG_DWORD,
			(LPBYTE) &g_iLastSaveType, sizeof(DWORD));

		if( !g_strLastSavePath.empty() )
			lResult = RegSetValueEx(hComposerKey, L"LastSavePath", 0, REG_SZ,
				(LPBYTE)g_strLastSavePath.c_str(), g_strLastSavePath.length()*sizeof(WCHAR)+1);
		if( !g_strLastImportFile.empty() )
			lResult = RegSetValueEx(hComposerKey, L"LastImportFile", 0, REG_SZ,
				(LPBYTE)g_strLastImportFile.c_str(), g_strLastImportFile.length()*sizeof(WCHAR)+1);
		if( !g_strSegImportPath.empty() )
			lResult = RegSetValueEx(hComposerKey, L"SegImportPath", 0, REG_SZ,
				(LPBYTE)g_strSegImportPath.c_str(),	g_strSegImportPath.length()*sizeof(WCHAR)+1);
//		if( !g_strVSTPath.empty() )
			lResult = RegSetValueEx(hComposerKey, L"VSTPluginsPath", 0, REG_SZ,
				(LPBYTE)g_strVSTPath.c_str(), g_strVSTPath.length()*sizeof(WCHAR)+1);
//		if( !g_strVSTPath.empty() )
			lResult = RegSetValueEx(hComposerKey, L"VSTiPluginsPath", 0, REG_SZ,
				(LPBYTE)g_strVSTiPath.c_str(), g_strVSTiPath.length()*sizeof(WCHAR)+1);

		DWORD dwRegValue = g_bShowRecordHint ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"ShowRecordHint", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bAlphaKey ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"ChordDisplayType", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bAutoOpenProject ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"AutoOpenProject", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bAutoOpenProjectEnable ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"AutoOpenProjectEnable", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bAutoDownloadStyle ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"AutoDownloadStyle", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bShowProtectMsg ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"ShowProtectMessage", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bShowVSTPath ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"ShowVSTPathHint", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bPrebeat ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"Prebeat", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_bExtFont ? 1 : 0;
		lResult = RegSetValueEx(hComposerKey, L"ExtendFont", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));
		dwRegValue = g_iToolPanelShow & 0x1;
		lResult = RegSetValueEx(hComposerKey, L"ToolPanelShow", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));

		lResult = RegSetValueEx(hComposerKey, L"PreStageMode", 0, REG_DWORD,
			(LPBYTE) &g_iPreStageDefault, sizeof(DWORD));

		lResult = RegSetValueEx(hComposerKey, L"SegColorMode", 0, REG_DWORD,
			(LPBYTE) &g_iSegColorMode, sizeof(DWORD));

		int index;
		for( index=0; index<g_lstRecentProject.size() && index<MAX_RECENT_PROJECT; index++ ){
			wstring strValueName = L"RecentProject";
			strValueName += IntToStr(index + 1).c_str();
			lResult = RegSetValueEx(hComposerKey, strValueName.c_str(), 0,
				REG_SZ, (LPBYTE)g_lstRecentProject[index].c_str(),
				g_lstRecentProject[index].length()*sizeof(WCHAR) + 1);
		}

		// 删除多余的工程文件
		for( ; index<MAX_RECENT_PROJECT; index++ ){
			wstring strValueName = L"RecentProject";
			strValueName += IntToStr(index + 1).c_str();

			if (ERROR_SUCCESS == RegQueryValueEx(hComposerKey,
				strValueName.c_str(), NULL, NULL, NULL, NULL)) {
				RegDeleteValue(hComposerKey, strValueName.c_str());
			}
		}

		// mac address
		dwRegValue = g_lstMacAddress.size();// + g_lstMacAddressNew.size();
		lResult = RegSetValueEx(hComposerKey, L"deviceNum", 0, REG_DWORD,
			(LPBYTE) &dwRegValue, sizeof(DWORD));

		for( int i=0; i<g_lstMacAddress.size(); i++) {
			String strDeviece = L"device";
			strDeviece += IntToStr(i);

			lResult = RegSetValueEx(hComposerKey, strDeviece.c_str(), 0, REG_BINARY,
								g_lstMacAddress[i], 6);
		}

//		for( int indexNew=0; indexNew<g_lstMacAddressNew.size(); indexNew++) {
//
//			String strDeviece = L"device";
//			strDeviece += IntToStr(indexDev);
//
//			lResult = RegSetValueEx(hComposerKey, strDeviece.c_str(), 0, REG_BINARY,
//				g_lstMacAddressNew[indexNew], 6);
//
//			indexDev++;
//		}

		RegCloseKey(hComposerKey);
	}
}

void GetInitVar() {
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;

	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_SOFTWARE, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		if (dwDisposition == REG_OPENED_EXISTING_KEY) {
			DWORD dwSize = MAX_PATH, dwType;
			BYTE szBuffer[MAX_PATH];

			lResult = RegQueryValueEx(hComposerKey, L"FontName", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				strcpy( g_strSoundFont, szBuffer );
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"LastSavePath", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strLastSavePath = (TCHAR*)szBuffer;
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"LastImportFile", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strLastImportFile = (TCHAR*)szBuffer;
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"SegImportPath", NULL, NULL,
							szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strSegImportPath = (TCHAR*)szBuffer;
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"VSTPluginsPath", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strVSTPath = (TCHAR*)szBuffer;
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"VSTiPluginsPath", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strVSTiPath = (TCHAR*)szBuffer;
			}

			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"ExtFontsDir", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strExtFontsPath = (TCHAR*)szBuffer;
			}

			int nValue;
			dwSize = sizeof(int);
			lResult = RegQueryValueEx(hComposerKey, L"ToolPanelShow", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				if( nValue<0 || nValue>1 )
					nValue = 0;
				g_iToolPanelShow = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"TimeSignature", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				if( nValue<0 || nValue>3 )
					nValue = 0;
				g_iMelodyTimeSignature = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"Tempo", NULL, &dwType,
				(LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				if( nValue<50 || nValue>200 )
					nValue = 75;
				g_nMelodyTempo = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"PlaybackDevice", NULL, &dwType,
				(LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iPlaybackDevice = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"PlaybackOutput", NULL, &dwType,
				(LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iPlaybackOutput = nValue;
			}
			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"PlaybackDeviceName", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				strcpy( g_strPlaybackDevice, szBuffer );
			}
			lResult = RegQueryValueEx(hComposerKey, L"RecordDevice", NULL, &dwType,
				(LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iRecordDevice = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"RecordInput", NULL, &dwType,
				(LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iRecordInput = nValue;
			}
			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, L"RecordDeviceName", NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				strcpy( g_strRecordDevice, szBuffer );
			}
			lResult = RegQueryValueEx(hComposerKey, L"RecordAutoAdjust", NULL, &dwType,
				(LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bRecordAutoAdjust = nValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"LastSaveOption2", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iLastSaveOption = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"WindowState", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iWindowState = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"LastSaveType", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iLastSaveType = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"ShowRecordHint", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bShowRecordHint = nValue ? true : false;
			}

			dwSize = sizeof(int);
			lResult = RegQueryValueEx(hComposerKey, L"AutoSave", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bAutoSave = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"AutoOpenProject", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bAutoOpenProject = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"AutoOpenProjectEnable", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bAutoOpenProjectEnable = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"AutoDownloadStyle", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bAutoDownloadStyle = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"ShowProtectMessage", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bShowProtectMsg = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"ShowVSTPathHint", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bShowVSTPath = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"Prebeat", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bPrebeat = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"ExtendFont", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bExtFont = nValue;
			}

			lResult = RegQueryValueEx(hComposerKey, L"ChordDisplayType", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_bAlphaKey = nValue ? true : false;
			}

			lResult = RegQueryValueEx(hComposerKey, L"PreStageMode", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				g_iPreStageDefault = nValue;
				if( g_iPreStageDefault>2 )
					g_iPreStageDefault = 2;
				g_iPreStage = g_iPreStageDefault;
			}

			lResult = RegQueryValueEx(hComposerKey, L"SegColorMode", NULL,
				&dwType, (LPBYTE) &nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				if( nValue>1 || nValue<0 )
					nValue = 1;

				g_iSegColorMode = nValue;
			}

			float fValue;
			dwSize = sizeof(float);
			lResult = RegQueryValueEx(hComposerKey, L"RecordVolume", NULL,
				&dwType, (LPBYTE) & fValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
 				if( fValue<0 || fValue>1 )
					fValue = 1;

				g_fRecordVolume = fValue;
			}
			lResult = RegQueryValueEx(hComposerKey, L"SpeakerVolume", NULL,
				&dwType, (LPBYTE) & fValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
 				if( fValue<0 || fValue>1 )
					fValue = 1;

				g_fSpeakerVolume = fValue;
			}

			for (int i = 0; i < MAX_RECENT_PROJECT; i++) {
				wstring strValueName = L"RecentProject";
				strValueName += IntToStr(i + 1).c_str();

				dwSize = MAX_PATH;
				lResult = RegQueryValueEx(hComposerKey, strValueName.c_str(),
					NULL, NULL, szBuffer, &dwSize);
				if (lResult == ERROR_SUCCESS && dwSize > 0) {
					g_lstRecentProject.push_back((LPCTSTR)szBuffer);
				}
			}

			if( !g_lstRecentProject.empty() ){
				g_strLastProjSavePath = ExtractFilePath( g_lstRecentProject[0].c_str() ).c_str();
			}

			//mac address
			lResult = RegQueryValueEx(hComposerKey, L"deviceNum", NULL,
				&dwType, (LPBYTE) & nValue, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize>0 && nValue>0 ) {
				for(int index=0; index<nValue; index++) {
					BYTE *szBuffer = new char[6];
					dwSize = 6;
					String strDeviece = L"device";
					strDeviece += IntToStr(index);

					lResult = RegQueryValueEx(hComposerKey, strDeviece.c_str(), NULL, NULL,	szBuffer, &dwSize);
					if (lResult == ERROR_SUCCESS && dwSize > 0 && szBuffer[0]!=0) {
						g_lstMacAddress.push_back(szBuffer);
					}else{
						SAFE_DELETE(szBuffer)
					}
				}
			}
		}
		RegCloseKey(hComposerKey);
	}
}

void SetAutoLogin(bool bAuto, LPCSTR strName, LPCSTR strPwd) {
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;
	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_SOFTWARE, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);
	if (lResult == ERROR_SUCCESS) {
		BYTE strText[100];
		int nNameLen = strlen(strName), nRegLen = nNameLen + 1;
		strText[0] = nNameLen;
		for (int i = 0; i < nNameLen; i++) {
			strText[i + 1] = strName[i] - 0x63;
		}
		strText[nNameLen + 1] = '\0';

		if (bAuto) {
			int nMaxPwdLen = 16, nPwdLen = strlen(strPwd);
			strText[nNameLen + 1] = nPwdLen;

			for (int i = 0; i < nMaxPwdLen; i++) {
				if (i < nPwdLen)
					strText[i + nNameLen + 2] = strPwd[i] - 0x4B;
				else
					strText[i + nNameLen + 2] = Random(256);
			}
			strText[nNameLen + nMaxPwdLen + 2] = '\0';

			nRegLen += 17;
		}

		lResult = RegSetValueEx(hComposerKey, REGKEY_AUTOLOG, 0, REG_BINARY,
			strText, nRegLen);

		RegCloseKey(hComposerKey);
	}
}

bool GetAutoLogin(char* strName, char* strPwd) {
	HKEY hComposerKey;
	DWORD dwDisposition;
	bool bAuto = false;
	strName[0] = strPwd[0] = 0;

	long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_SOFTWARE, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);
	if (lResult == ERROR_SUCCESS) {
		DWORD dwSize;
		BYTE szBuffer[MAX_PATH];
		if (dwDisposition == REG_OPENED_EXISTING_KEY) {
			dwSize = MAX_PATH;
			lResult = RegQueryValueEx(hComposerKey, REGKEY_AUTOLOG, NULL, NULL,
				szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				int nTextLen = dwSize;
				int nNameLen = szBuffer[0];
				for (int i = 0; i < nNameLen; i++) {
					strName[i] = szBuffer[i + 1] + 0x63;
				}
				strName[nNameLen] = '\0';

				if (nNameLen == nTextLen - 18) {
					bAuto = true;
					int nPwdLen = szBuffer[nNameLen + 1];
					for (int i = 0; i < nPwdLen; i++) {
						strPwd[i] = szBuffer[i + nNameLen + 2] + 0x4B;
					}
					strPwd[nPwdLen] = '\0';
				}
			}
		}

		RegCloseKey(hComposerKey);
	}

	return bAuto;
}

void GetAutoSaveReg()
{
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;

	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_SOFTWARE, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		if (dwDisposition == REG_OPENED_EXISTING_KEY) {
			DWORD dwSize = MAX_PATH;
			BYTE szBuffer[MAX_PATH];

			lResult = RegQueryValueEx(hComposerKey, L"AutoSaveProj", NULL, NULL, szBuffer, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 1) {
				g_strProjectName = (TCHAR*)szBuffer;
			}
		}

		RegCloseKey(hComposerKey);
	}
}

void SetAutoSaveReg( bool bAuto )
{
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;
	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, (TCHAR*)REGKEY_SOFTWARE, 0,
		NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		DWORD dwValue = bAuto;
		lResult = RegSetValueEx(hComposerKey, L"AutoSave", 0, REG_DWORD,
			(LPBYTE) & dwValue, sizeof(DWORD));

		if( bAuto )
			lResult = RegSetValueEx(hComposerKey, L"AutoSaveProj", 0, REG_SZ,
						(LPBYTE)g_strProjectName.c_str(),
						g_strProjectName.length()*sizeof(WCHAR) + 1);
		else
			lResult = RegSetValueEx(hComposerKey, L"AutoSaveProj", 0, REG_SZ,
						NULL, 0 );

		RegCloseKey(hComposerKey);
	}

	g_bAutoSave = bAuto;
}

void DisableAutoOpen()
{
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;
	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, (TCHAR*)REGKEY_SOFTWARE, 0,
		NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		DWORD dwValue = 0;
		lResult = RegSetValueEx(hComposerKey, L"AutoOpenProjectEnable", 0, REG_DWORD,
			(LPBYTE) & dwValue, sizeof(DWORD));

		RegCloseKey(hComposerKey);
	}

	g_bAutoOpenProjectEnable = false;
}

void CheckVSTScanReg()
{
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;

	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_SOFTWARE, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		if (dwDisposition == REG_OPENED_EXISTING_KEY) {
			DWORD iScanning = 0, dwType, dwSize = sizeof(int);
			lResult = RegQueryValueEx(hComposerKey, L"VSTScanning", 0, &dwType, (LPBYTE)&iScanning, &dwSize);
			if (lResult == ERROR_SUCCESS && dwSize > 0) {
				if( iScanning==1 && !g_strVSTPath.empty() ){
					g_strVSTPath.clear();
					lResult = RegSetValueEx(hComposerKey, L"VSTPluginsPath", 0, REG_SZ,
							(LPBYTE)g_strVSTPath.c_str(), g_strVSTPath.length()*sizeof(WCHAR)+1);
				}
				else if( iScanning==2 && !g_strVSTiPath.empty() ){
					g_strVSTiPath.clear();
					lResult = RegSetValueEx(hComposerKey, L"VSTiPluginsPath", 0, REG_SZ,
							(LPBYTE)g_strVSTiPath.c_str(), g_strVSTiPath.length()*sizeof(WCHAR)+1);
				}

				if( iScanning!=0 ){
					iScanning = 0;
					lResult = RegSetValueEx(hComposerKey, L"VSTScanning", 0, REG_DWORD,
															(LPBYTE)&iScanning, sizeof(DWORD));
				}
			}
		}

		RegCloseKey(hComposerKey);
	}
}

void SetVSTScanReg( int iScanning )
{
	HKEY hComposerKey;
	DWORD dwDisposition;
	long lResult;
	lResult = RegCreateKeyEx(HKEY_CURRENT_USER, (TCHAR*)REGKEY_SOFTWARE, 0,
		NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hComposerKey,
		&dwDisposition);

	if (lResult == ERROR_SUCCESS) {
		lResult = RegSetValueEx(hComposerKey, L"VSTScanning", 0, REG_DWORD,
										(LPBYTE)&iScanning, sizeof(DWORD));

		RegCloseKey(hComposerKey);
	}
}

int GetMidiTrackData( int &nLen, BYTE* pData, int iMT, int iSBar, int iEBar, int* piPlayBar, int* piLenBar )
{
	int ret = 0;

	TMidiTrack* pMT = g_aMidiTracks[iMT];
	TStage* aStages = new TStage[g_Opus.StageCount()];
	int nStageNum = 0;

	int iEndBar = iEBar<0 ? g_Opus.BarCount()-1 : iEBar;
	int iStartBar = iSBar<0 ? 0 : iSBar;
	if( piLenBar )
		*piLenBar = iEndBar - iStartBar + 1;

	int iFBar, iStage = FindStage( iStartBar, &iFBar ),
		iLBar = iFBar;

	int iPlayBar = -1;
	while( iStage<g_Opus.StageCount() ){
		TOpusStage* pStage = g_lstOpusStages[iStage];

		aStages[nStageNum].iSegType = pStage->iSegType;
		aStages[nStageNum].iSegKey = pStage->iSegKey;
		aStages[nStageNum].nBarNum = pStage->aBars.size();

		for( int i=0; i<pStage->aTracks.size(); i++ ){
			TTrack* pTrack = pStage->aTracks[i];

			if( pTrack->iFile==pMT->file && pTrack->iChanSpec==pMT->chno ){
				aStages[nStageNum].nTrkNum = 1;
				aStages[nStageNum].aTracks = new TComposeTrack[1];

				TComposeTrack& track = aStages[nStageNum].aTracks[0];
				track.iStyleLoc = pTrack->iStyleLoc;
				track.iStyleId = pTrack->iStyleId;
				track.iChanNo = pTrack->iChanNo;
				track.iChanSpec = pTrack->iChanSpec;
				track.iProg = pTrack->iProg;
				track.nVol = pTrack->nVol < 0 ? 0
							: pTrack->nVol * ( pStage->nVol / 100.0 ) * ( pMT->volume / 100.0 );

				if( pStage->iSegType<=SEGTYPE_FILL ){
					track.iSegNo = pTrack->iSegNo;

					aStages[nStageNum].aChords = new TBarChords[aStages[nStageNum].nBarNum];
					for( int j=0; j<aStages[nStageNum].nBarNum; j++ ){
						memcpy( &aStages[nStageNum].aChords[j],
									&pStage->aBars[j]->aChords,
									sizeof(TBarChords) );
					}
				}
				else{
					int cType = (pTrack->iSegNo / 4 + 1) << 4;
					int sno = pTrack->iSegNo % 4;
					track.iSegNo = sno + cType;
				}

				if( iPlayBar<0 ){
					iPlayBar = iLBar;
				}

				break;
			}
		}

		bool bMerge = false;
		if( bMerge ){
			int barBefore = aStages[nStageNum-1].nBarNum,
				barAfter = barBefore + aStages[nStageNum].nBarNum;
			aStages[nStageNum-1].nBarNum = barAfter;

			if( aStages[nStageNum-1].aChords && aStages[nStageNum].aChords ){
				aStages[nStageNum-1].aChords = (TBarChords*)realloc( aStages[nStageNum-1].aChords,
															sizeof(TBarChords) * barAfter );
				memcpy( &aStages[nStageNum-1].aChords[barBefore], aStages[nStageNum].aChords,
													sizeof(TBarChords) * ( barAfter - barBefore ));

				delete[] aStages[nStageNum].aChords;
				aStages[nStageNum].aChords = NULL;
			}

			if( aStages[nStageNum].aTracks ){
				delete[] aStages[nStageNum].aTracks;
				aStages[nStageNum].aTracks = NULL;
			}
		}
		else
			nStageNum++;

		iLBar += pStage->aBars.size();
		if( iLBar>iEndBar ){
			aStages[nStageNum-1].nBarNum -= iLBar - iEndBar - 1;
			break;
		}
		else{
			iStage++;
		}
	}

	if( piPlayBar ){
		if( iPlayBar>iStartBar )
			iStartBar = iPlayBar;

		iStartBar -= iFBar;
		*piPlayBar = iStartBar;
    }

	ret = f_CM_Compose( &nLen, pData, g_iMelodyTimeSignature, g_nMelodyTempo,
										nStageNum, aStages, false, NULL, NULL );

	SAFE_DELETE_ARRAY(aStages);

	return ret;
}

int GetComposeData( TOpusStageList lstOpusStages, int iKey, int& nDataSize,
															LPBYTE lpData, bool bSave )
{
	DebugPrint("//////////////////曲式分段输出/////////////////////");

	int nStageNum = lstOpusStages.size(),
		count = 0;
	TStage* aStages = NULL;
	if (nStageNum > 0) {
		aStages = new TStage[nStageNum];

		for( int i = 0; i<nStageNum; i++ ){
			if( i>0 && lstOpusStages[i]->iSegType<=SEGTYPE_FILL
							&& lstOpusStages[i-1]->iSegType==lstOpusStages[i]->iSegType
							&& !DiffStages( lstOpusStages[i-1], lstOpusStages[i], true ) ){
				int last = count - 1,
					nBefore = aStages[last].nBarNum,
					nAfter = nBefore + lstOpusStages[i]->aBars.size();
				aStages[last].nBarNum = nAfter;
				aStages[last].aChords = (TBarChords*)realloc( aStages[last].aChords,
															sizeof(TBarChords) * nAfter );
				for( int j=0; j<lstOpusStages[i]->aBars.size(); j++ ){
					memcpy( &aStages[last].aChords[nBefore+j],
									&lstOpusStages[i]->aBars[j]->aChords,
									sizeof(TBarChords) );
				}
			}
			else{
				aStages[count].iSegType = lstOpusStages[i]->iSegType;
				aStages[count].iSegKey = lstOpusStages[i]->iSegKey;

				aStages[count].nTrkNum = lstOpusStages[i]->aTracks.size();
				if( aStages[count].nTrkNum>0 ){
					aStages[count].aTracks = new TComposeTrack[aStages[count].nTrkNum];
					for( int j=0; j<aStages[count].nTrkNum; j++ ){
						TTrack* pTrack = lstOpusStages[i]->aTracks[j];
						TComposeTrack& pCompTrack = aStages[count].aTracks[j];

						pCompTrack.iStyleLoc = pTrack->iStyleLoc;
						pCompTrack.iStyleId = pTrack->iStyleId;
						pCompTrack.iSegNo = pTrack->iSegNo;
						pCompTrack.iChanNo = pTrack->iChanNo;
						pCompTrack.iChanSpec = pTrack->iChanSpec;
						pCompTrack.iProg = pTrack->iProg;
						pCompTrack.iFile = pTrack->iFile;
						pCompTrack.nVol = pTrack->nVol<0 ? 0 : pTrack->nVol * lstOpusStages[i]->nVol / 100.0;

						if( pCompTrack.nVol>0 && bSave ){
							TMidiTrack* pMT = g_Midi.FindMidiTrack( pTrack->iFile, pTrack->iChanSpec );
							pCompTrack.nVol *= pMT->volume / 100.0;
						}

						if( aStages[count].iSegType>=SEGTYPE_INTRO ){
							char cType = (pTrack->iSegNo / 4 + 1) << 4;
							char sno = pTrack->iSegNo % 4;
							pCompTrack.iSegNo = sno + cType;
						}
					}
				}

				aStages[count].nBarNum = lstOpusStages[i]->aBars.size();
				if( aStages[count].iSegType<=SEGTYPE_FILL ){
					aStages[count].aChords = new TBarChords[aStages[count].nBarNum];
					for( int j=0; j<aStages[count].nBarNum; j++ ){
						memcpy( &aStages[count].aChords[j],
									&lstOpusStages[i]->aBars[j]->aChords,
									sizeof(TBarChords) );
					}
				}

				count++;
			}
		}
	}

	HRESULT ret = f_CM_Compose( &nDataSize, lpData, g_iMelodyTimeSignature, g_nMelodyTempo,
															count, aStages, bSave, NULL, NULL );

	DebugPrint("Compose return buffer size = %d.\n", nDataSize);

	SAFE_DELETE_ARRAY(aStages);

	return ret;
}

bool GenerateCompose()
{
	HRESULT hr = S_OK;

	SaveAutoProj();

	if( !g_Opus.CheckModified(CHECK_STAGEALL) ){
		return true;
	}

	f_MM_Stop();
	f_MM_FreeComposes();
	g_Midi.ClearMidiTrackNotes();
  	g_Opus.Backup();
//	g_bSongSaved = false;

	if( g_Opus.StageCount()==0 )
		return true;

	int nStageNum = g_Opus.StageCount();
	BYTE *pData = new BYTE[2000000],
		*notesBuff = new BYTE[1000000];

	vector<BYTE> arrFiles;
	arrFiles.push_back( 0 );

	for( int b=0; b<arrFiles.size(); b++ ){
		int nDataSize = 2000000,
			count = 0;
		BYTE iFile = arrFiles[b];
		BYTE iBank = 0xFF;
		bool bCompose = false;

		TStage* aStages = new TStage[nStageNum];
		for( int i = 0; i<nStageNum; i++ ){
			if( i>0 && g_lstOpusStages[i]->iSegType<=SEGTYPE_FILL
							&& g_lstOpusStages[i-1]->iSegType==g_lstOpusStages[i]->iSegType
							&& !DiffStages( g_lstOpusStages[i-1], g_lstOpusStages[i], true, false ) ){
				int last = count - 1,
					nBefore = aStages[last].nBarNum,
					nAfter = nBefore + g_lstOpusStages[i]->aBars.size();
				aStages[last].nBarNum = nAfter;
				aStages[last].aChords = (TBarChords*)realloc( aStages[last].aChords,
															sizeof(TBarChords) * nAfter );
				for( int j=0; j<g_lstOpusStages[i]->aBars.size(); j++ ){
					memcpy( &aStages[last].aChords[nBefore+j],
									&g_lstOpusStages[i]->aBars[j]->aChords,
									sizeof(TBarChords) );
				}
			}
			else{
				TOpusStage* pOpusStage = g_lstOpusStages[i];

				aStages[count].iSegType = pOpusStage->iSegType;
				aStages[count].iSegKey = pOpusStage->iSegKey;

				vector<TTrack*> arrTracks;
				for( int j=0; j<pOpusStage->aTracks.size(); j++ ){
					TTrack* pTrack = pOpusStage->aTracks[j];

					if( pTrack->iFile==iFile ){
						arrTracks.push_back( pTrack );
						if( iBank!=pTrack->iBank )
							iBank = pTrack->iBank;
					}
					else if( iFile==0 ){
						bool bNewFile = true;
						for( int k=1; k<arrFiles.size(); k++ ){
							if( arrFiles[k]==pTrack->iFile ){
								bNewFile = false;
								break;
							}
						}

						if( bNewFile )
							arrFiles.push_back( pTrack->iFile );
					}
				}

				if( !arrTracks.empty() ){
					bCompose = true;
					int nTrackNum = arrTracks.size();
					aStages[count].nTrkNum = nTrackNum;
					aStages[count].aTracks = new TComposeTrack[ nTrackNum ];

					for( int j=0; j<nTrackNum; j++ ){
						TTrack* pTrack = arrTracks[j];
						TComposeTrack& pCompTrack = aStages[count].aTracks[j];

						pCompTrack.iStyleLoc = pTrack->iStyleLoc;
						pCompTrack.iStyleId = pTrack->iStyleId;
						pCompTrack.iSegNo = pTrack->iSegNo;
						pCompTrack.iChanNo = pTrack->iChanNo;
						pCompTrack.iChanSpec = pTrack->iChanSpec;
						pCompTrack.iProg = pTrack->iProg;
						pCompTrack.iFile = pTrack->iFile;
						pCompTrack.nVol = pTrack->nVol<0 ? 0 : pTrack->nVol * pOpusStage->nVol / 100.0;

						if( aStages[count].iSegType>=SEGTYPE_INTRO ){
							char cType = (pTrack->iSegNo / 4 + 1) << 4;
							char sno = pTrack->iSegNo % 4;
							pCompTrack.iSegNo = sno + cType;
						}
					}
				}

				aStages[count].nBarNum = pOpusStage->aBars.size();
				if( aStages[count].iSegType<=SEGTYPE_FILL ){
					aStages[count].aChords = new TBarChords[aStages[count].nBarNum];
					for( int j=0; j<aStages[count].nBarNum; j++ ){
						memcpy( &aStages[count].aChords[j],
									&pOpusStage->aBars[j]->aChords,
									sizeof(TBarChords) );
					}
				}

				count++;
			}
		}

		if( bCompose || iFile==0 ){
			int lenNotes = 1000000;

			HRESULT ret = f_CM_Compose( &nDataSize, pData, g_iMelodyTimeSignature, g_nMelodyTempo,
														count, aStages, false, &lenNotes, notesBuff );

			if( ret==0 ){
				DebugPrint("File %d(Bank %d) compose  return buffer size = %d.\n", iFile, iBank, nDataSize);

				char* strFile = NULL;
				if( iBank==0xFF || iBank<0x80 ){
					strFile = iBank==0xFF ? NULL : g_lstFonts[iBank]->strFileName;
				}
				else{
					strFile = g_lstVSTi[iBank-0x80]->strFileName;
				}

				if( S_OK==f_MM_LoadCompose( iFile, pData, nDataSize, iBank, strFile ) ){
					DebugPrint("Load File %d(bank %d) compose ok.\n", iFile, iBank);

					if( lenNotes>0 ){
						int iPos = 0,
							nTrackSize = notesBuff[iPos++];
						double dblTPM = 192.0 * g_nBPM;
						for( int t=0; t<nTrackSize; t++ ){
							int chNo = notesBuff[iPos++],
								iStage = -1,
								vol = 0;
							TMidiTrack* pMT = g_Midi.FindMidiTrack( iFile, chNo );

							WORD seqSize = *(WORD*)(notesBuff + iPos);
							iPos += 2;

							for( WORD s=0; s<seqSize; s++ ){
								DWORD tick = *(DWORD*)(notesBuff + iPos),
									tkShow = (DWORD)((double)tick * POINTS_PER_BAR / dblTPM + 0.5);
								iPos += 4;

								int iShowStage = FindStage( tkShow/POINTS_PER_BAR );
								if( iShowStage!=iStage ){
									iStage = iShowStage;

									if( iStage>=0 ){
										TOpusStage* pStage = g_lstOpusStages[iStage];
										for( int trk=0; trk<pStage->aTracks.size(); trk++ ){
											TTrack* pTrack = pStage->aTracks[trk];
											if( pTrack->iFile==iFile && pTrack->iChanSpec==chNo ){
												vol = pTrack->nVol<0 ? 0 : pTrack->nVol * pStage->nVol / 100.0;
												break;
											}
										}
									}
								}

								WORD noteSize = *(WORD*)(notesBuff + iPos);
								iPos += 2;

								for( WORD n=0; n<noteSize; n++ ){
									BYTE pt = notesBuff[iPos++],
										vel = notesBuff[iPos++];

									if( pMT ){
										if( vel>0 ){
											pMT->aNotes.push_back( new TMidiNote( pt, vel, vol, tkShow ));
											if( pMT->ptMin>pt )
												pMT->ptMin = pt;
											if( pMT->ptMax<pt )
												pMT->ptMax = pt;
										}
										else{
											for( int r=pMT->aNotes.size()-1; r>=0; r-- ){
												TMidiNote* pNote = pMT->aNotes[r];
												if( pNote->pitch==pt && pNote->tkOff<0 ){
													pNote->tkOff = tkShow;

													if( pNote->tkOff==pNote->tkOn )
														pNote->tkOff++;

													break;
												}
											}
										}
									}
								}
							}

							for( int n=pMT->aNotes.size()-1; n>=0; n-- ){
								TMidiNote* pNote = pMT->aNotes[n];
								if( pNote->tkOff<0 ){
									delete pNote;
									pMT->aNotes.erase( pMT->aNotes.begin()+n );
								}
							}
						}
					}
				}
				else{
					hr = S_FALSE;

					DebugPrint("Load bank %d compose error.\n", iBank);
				}
			}
			else{
				hr = S_FALSE;

				DebugPrint("Bank %d compose error.\n", iBank );
			}
		}

		SAFE_DELETE_ARRAY(aStages);
	}

	delete[] pData;
 	delete[] notesBuff;

//	g_Opus.Backup();
//	g_bSongSaved = false;

	if( hr==S_OK ){
		SetTrackParams();
		g_bRecProtect = IsProtected();
		f_MM_SetRecordProtect( g_bRecProtect );
	}

	return hr == S_OK;
}

bool IsProtected()
{
	if( g_iPreStage==0 || SOFTWARE_ID==e_Pro_Lite
						|| g_bLogon && g_infoUser.accountInfo.vipPeriod!=0 )
		return false;

	//未付费风格检测
	vector<UINT> aStyleID;

	for( int i=0; i<g_lstOpusStages.size(); i++ ){
		TOpusStage* pStage = g_lstOpusStages[i];

		for( int j=0; j<pStage->aTracks.size(); j++ ){
			TTrack* pTrack = pStage->aTracks[j];

			if( pTrack->iStyleLoc==0 ){
				bool bChecked = false;
				for( int k=0; k<aStyleID.size(); k++ ){
					if( aStyleID[k]==pTrack->iStyleId ){
						bChecked = true;
						break;
					}
				}

				if( !bChecked ){
					bool bPaied = false;
					if( g_bLogon ){
						for( int c=0; c<g_infoUser.ownStyleNum; c++ ){
							if( g_infoUser.arrStyleId[c]==pTrack->iStyleId ){
								bPaied = true;
								break;
							}
						}
					}

					if( !bPaied ){
						TPROSTYLE infoStyle;
						infoStyle.pOrigin = new TSTYLEORIGIN;
						f_CM_GetStyleInfo( pTrack->iStyleLoc, pTrack->iStyleId, &infoStyle);
						if( infoStyle.pOrigin->cost > 0 ){
							return true;
						}
					}

					aStyleID.push_back( pTrack->iStyleId );
				}
			}
		}
	}

	return false;
}
/*
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->pStyle || GetStyleInfo( -1, 0 ) )
		return E_PROJ_UNSAVEDTEMPSTYLE;


	return E_PROJ_NOERROR;
}
*/
void SetTransparent( TComponent* pCtrl )
{
	if( pCtrl->ClassNameIs( TLabel::ClassName() ) ){
		((TLabel*)pCtrl)->ControlStyle>>csOpaque;
	}
/*	else if( pCtrl->ClassNameIs( TCheckBox::ClassName() ) ){
		((TCheckBox*)pCtrl)->Color = RGB(230, 204, 179);
	}
	else if( pCtrl->ClassNameIs( TRadioButton::ClassName() ) ){
		((TRadioButton*)pCtrl)->Color = RGB(230, 204, 179);
	}
*/	else{
		for( int i=0; i<pCtrl->ComponentCount; i++ ){
			SetTransparent( pCtrl->Components[i] );
		}
    }
}

char* GetMacAdress()
{
	//首先选择原用id
	if(!g_lstMacAddress.empty())
		return g_lstMacAddress[0];

	char *idDevice = new char[6];
	*(UINT*)idDevice = time(NULL);
	*(USHORT*)(idDevice+4) = Random(65536);
	g_lstMacAddress.push_back(idDevice);

	return g_lstMacAddress[0];
//	PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
//	unsigned long stSize = sizeof(IP_ADAPTER_INFO);
//	int nRes = GetAdaptersInfo(pIpAdapterInfo, &stSize);
//
//	if( ERROR_BUFFER_OVERFLOW==nRes ){
//
//		SAFE_DELETE(pIpAdapterInfo)
//		pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
//		nRes=GetAdaptersInfo(pIpAdapterInfo, &stSize);
//	}
//
//	if( ERROR_SUCCESS==nRes ){
//
//		while( pIpAdapterInfo )
//		{
//			char *idDevice = new char[6];
//			for(int index=0; index<pIpAdapterInfo->AddressLength; index++) {
//
//				idDevice[index] = pIpAdapterInfo->Address[index];
//			}
//
//			g_lstMacAddressNew.push_back(idDevice);
//
//			pIpAdapterInfo = pIpAdapterInfo->Next;
//		}
//	}
//	SAFE_DELETE(pIpAdapterInfo)
//
//	int nEqualIndex = -1;
//	for(int indexNew=0; indexNew<g_lstMacAddressNew.size(); indexNew++){
//
//		char *szBufferNew = g_lstMacAddressNew[indexNew];
//
//		for(int indexOld=0; indexOld<g_lstMacAddress.size(); indexOld++) {
//
//			char *szBufferOld = g_lstMacAddress[indexOld];
//
//			bool bEqual = true;
//			for(int i=0; i<6; i++)
//				if(szBufferOld[i]!=szBufferNew[i]) bEqual = false;
//			if( bEqual ) {
//				nEqualIndex = indexOld;
//				break;
//			}
//		}
//
//		if( -1!=nEqualIndex ) break;
//	}
//
//	if( -1==nEqualIndex && g_lstMacAddressNew.size() ) {
//
//		return g_lstMacAddressNew[0];
//
//	}else if( nEqualIndex>=0 ) {
//
//		for(int i=0; i<g_lstMacAddressNew.size(); i++) {
//			SAFE_DELETE(g_lstMacAddressNew[i])
//		}
//		g_lstMacAddressNew.clear();
//
//		return g_lstMacAddress[nEqualIndex];
//
//	}else return NULL;
//
//	return NULL;
}

TColor u_clrSegment[4][12];

void InitSegmentColor()
{
	if( g_iSegColorMode==1 ){
		int clrSeed[4][2][3] = {{{250,244,213},{234,132, 59}}, 	// 伴奏颜色
								{{254,214,247},{224, 15,231}}, 	// 加花颜色
								{{196,230,147},{148,185,145}}, 	// 前奏颜色
								{{203,219,247},{164,180,205}}}; // 尾奏颜色

		u_clrSegment[0][0] = RGB( 250, 249, 225 );
		u_clrSegment[1][0] = RGB( 255, 225, 250 );
		u_clrSegment[2][0] = RGB( 200, 242, 147 );
		u_clrSegment[3][0] = RGB( 215, 224, 252 );

		for( int i=0; i<4; i++ ){
			int r0 = clrSeed[i][0][0],
				r1 = clrSeed[i][1][0],
				g0 = clrSeed[i][0][1],
				g1 = clrSeed[i][1][1],
				b0 = clrSeed[i][0][2],
				b1 = clrSeed[i][1][2];
			double dR = (r1-r0) / 11.0,
				   dG = (g1-g0) / 11.0,
				   dB = (b1-b0) / 11.0;

			u_clrSegment[i][1] = RGB( r0, g0, b0 );
			u_clrSegment[i][11] = RGB( r1, g1, b1 );

			for (int j=2; j<11; j++){
			   r0 += dR;
			   g0 += dG;
			   b0 += dB;

			   u_clrSegment[i][j] = RGB( r0, g0, b0 );
			}
		}
	}
	else{
		int clrSeed[4][8][3] = {{{250,244,213},{248,235,159}, // 伴奏颜色
								 {247,224,128},{244,205,100},
								 {246,187, 95},{246,172, 82},
								 {244,149, 64},{234,132, 59}},
								{{254,214,247},{246,193,241},  // 加花颜色
								 {240,172,236},{238,149,234},
								 {236,111,231},{236, 75,231},
								 {236, 47,231},{224, 15,231}},
								{{196,230,147},{179,215,176},  // 前奏颜色
								 {164,200,161},{148,185,145}},
								{{203,219,247},{189,206,230},  // 尾奏颜色
								 {177,193,220},{164,180,205}}};

		u_clrSegment[0][0] = RGB( 250, 249, 225 );
		u_clrSegment[1][0] = RGB( 255, 225, 250 );
		u_clrSegment[2][0] = RGB( 200, 242, 147 );
		u_clrSegment[3][0] = RGB( 215, 224, 252 );

		for( int i=0; i<4; i++ ){
			int end = i<SEGTYPE_INTRO ? 8 : 4;

			for( int j=0; j<end; j++ ){
				u_clrSegment[i][j+1] = RGB( clrSeed[i][j][0],
											clrSeed[i][j][1],
											clrSeed[i][j][2] );
			}
		}
	}
}

TColor GetSegmentColor( int iSegType, int iNo, bool bIncrease )
{
	if( g_iSegColorMode==0 ){
		int mod = iSegType<SEGTYPE_INTRO ? 8 : 4;
		iNo %= mod;
	}

	if( bIncrease )
		iNo++;

	if( iNo>11 )
		iNo = 11;

	return u_clrSegment[iSegType][iNo];
}

