INT_PTR CSettingsDialog::OnCommand(WPARAM wParam) 
{
    switch LOWORD(wParam) {
        case IDC_BUTTON_FONT:
        {
            selectColor(newSettings.fontColor);
            break;
        }
        case IDC_BUTTON_BACKGROUND:
        {
            selectColor(newSettings.bgColor);
            break;
        }
        case IDC_CHECK1:
        {
            preview = (IsDlgButtonChecked(handle, IDC_CHECK1) == BST_CHECKED);
            break;
        }
        case IDOK:
        {
            updateSettings(newSettings);
            EndDialog(handle, wParam);
            return TRUE;
        }
        case IDCANCEL:
        {
            updateSettings(oldSettings);
            EndDialog(handle, wParam);
            return TRUE;
        }
    }
    tryUpdate();
    return FALSE;
}
void CSettingsDialog::OnScroll(WPARAM wParam, LPARAM lParam) {
    HWND commandHandle = reinterpret_cast<HWND>(lParam);
    if( commandHandle == GetDlgItem(handle, IDC_SLIDER_FONTSIZE) ) {
        newSettings.font.lfHeight = SendMessage(GetDlgItem(handle, IDC_SLIDER_FONTSIZE), TBM_GETPOS, 0, 0);
    } else if( commandHandle == GetDlgItem(handle, IDC_SLIDER_BACKGROUND_OPACITY) ) {
        newSettings.opacity = (BYTE)SendMessage(GetDlgItem(handle, IDC_SLIDER_BACKGROUND_OPACITY), TBM_GETPOS, 0, 0);
    }
    tryUpdate();
}
void SeqModel::tryForwardToStar( Dtw_Column_Link *link, int columnIdx, int stateID, double preCost) {
    if( states[stateID].leafForwardIdx == NIL_FORWARD ) 
        return ;

    double newCost = preCost + states[stateID].forwardCost;

//    if(states[stateID].leafForwardIdx == 1)
//        printf("xxd %lf\n", newCost);

    tryUpdate(link, columnIdx, stateID, states[stateID].leafForwardIdx, newCost);

    /*  
        if(!(newCost>= 0) && !(newCost<= 0)) {
            printf("Star %lf %lf %lf\n", preCost, states[stateID].forwardCost,  newCost);
                getchar();
        }
        */

}
DriveManagement::DriveManagement()
{
//    timer.start(60*1000);
//    connect(&timer,&QTimer::timeout,this,&DriveManagement::tryUpdate,Qt::QueuedConnection);
    tryUpdate();
    #ifdef Q_OS_WIN32
    reg1=QRegularExpression(QStringLiteral("^(\\\\\\\\|//)[^\\\\\\\\/]+(\\\\|/)[^\\\\\\\\/]+"));
    reg2=QRegularExpression(QStringLiteral("^((\\\\\\\\|//)[^\\\\\\\\/]+(\\\\|/)[^\\\\\\\\/]+).*$"));
    reg3=QRegularExpression(QStringLiteral("^[a-zA-Z]:[\\\\/]"));
    reg4=QRegularExpression(QStringLiteral("^([a-zA-Z]:[\\\\/]).*$"));
    #endif
    #ifdef ULTRACOPIER_PLUGIN_DEBUG
    int index=0;
    while(index<mountSysPoint.size())
    {
        ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("mountSysPoint: %1").arg(mountSysPoint.at(index)));
        index++;
    }
    #endif
}
void testAudioDataVideoSync(int prio) {
	u32 *buffer = (u32 *)getPsmfPlayerDisplayBuf() + 120;
	SceUID *psmf = createPsmfPlayerPlaying(TEST_VIDEO_FILENAME, prio);

	PsmfInfo info = {0};
	scePsmfPlayerGetPsmfInfo(psmf, &info);
	checkpoint("  Last frame is %d", info.lengthTS);

	memset(buffer, 0, 16);
	warmUpVideo(psmf);

	int myVideoPts = 0;
	int myAudioPts = audioStatus ? 0 : -4180;

	PsmfVideoData videoData = {0, getPsmfPlayerDisplayBuf()};
	for (int i = 0; i < 800; ++i) {
		u64 pts = 0;
		scePsmfPlayerGetCurrentPts(psmf, &pts);
		
		scePsmfPlayerUpdate(psmf);
		scePsmfPlayerUpdate(psmf);
		scePsmfPlayerUpdate(psmf);
		audioStatus = scePsmfPlayerGetAudioData(psmf, audioData) == 0;
		videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
		if (myVideoPts < myAudioPts)
			videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
		sceKernelDelayThread(16000);

		if (audioStatus)
			myAudioPts += 4180;
		if (videoStatus)
			myVideoPts = videoData.displaypts;

		if (pts >= info.lengthTS - 3003 - 3003) {
			break;
		}
		if (myAudioPts >= info.lengthTS - 3003) {
			break;
		}
	}
	
	checkpoint("  * At last frame? (status=%x)  pts=%d", scePsmfPlayerGetCurrentStatus(psmf), videoData.displaypts);
	tryUpdate("  After last frame 1", psmf);
	tryUpdate("  After last frame 2", psmf);

	videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
	testGetAudioData("  Read audio 1", psmf);
	checkpoint("  * Read frame 1 (status=%x)  pts=%d", scePsmfPlayerGetCurrentStatus(psmf), videoData.displaypts);
	tryUpdate("  After last frame 2", psmf);

	videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
	testGetAudioData("  Read audio  2", psmf);
	checkpoint("  * Read frame 2 (status=%x)  pts=%d", scePsmfPlayerGetCurrentStatus(psmf), videoData.displaypts);
	tryUpdate("  After last frame 3", psmf);

	videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
	videoStatus = scePsmfPlayerGetVideoData(psmf, &videoData) == 0;
	testGetAudioData("  Read audio 3", psmf);
	checkpoint("  * Read frame 3 (status=%x)  pts=%d", scePsmfPlayerGetCurrentStatus(psmf), videoData.displaypts);
	tryUpdate("  After last frame 4", psmf);
}
double SeqModel::forwardColumn(Dtw_Column_Link *link, WaveFeatureOP & wav, int columnIdx, double threshold) {
    double bestVal = Feature::IllegalDist;

//    assert(columnIdx < wav.size());
    if(columnIdx >= wav.size()) {
        Warn("Forwarding a columnIdx larger than wav SIZE!");
        return bestVal;
    }

    int rollIdx = getRollIdx( columnIdx );
    int preIdx = rollIdx ^ 1;

    int nextStateID;

    link[rollIdx].clear();

    for(int preStateID = link[preIdx].head; \
            preStateID != NIL_EDGE; \
            preStateID = link[preIdx].nodes[preStateID].next) {
        Dtw_Column_Node & dtw_node = link[preIdx].nodes[preStateID];

        double preCost = dtw_node.cost;
        double nextCost;

        // beam
        if(doBeam && Feature::better(threshold, preCost)) {
//            Log("beam %lf", threshold);
            continue;
        }

        // preStateID --- edges[eID] ---> nextStateID
        for(int eID = states[preStateID].head; \
                eID != NIL_EDGE; \
                eID = edges[eID].next) {
            nextStateID = edges[eID].to;

//            Log("Edge Cost: %lf\n", edges[eID].cost);

            nextCost = preCost + edges[eID].cost;

            /*  
        if(!(nextCost>= 0) && !(nextCost<= 0)) {
                printf("%lf %lf %lf\n", nextCost,preCost, edges[eID].cost);
                getchar();
        }
        */


            KMeanState * state = (KMeanState *)(states[nextStateID].hmmState);
            double nodeCost = state->nodeCost( &(wav[columnIdx]) );

            nextCost += nodeCost;

//            Log("Node Cost: %lf\n", nodeCost);
//            Log("Cost: %lf\n", nextCost);

            if(Feature::better(nextCost, bestVal)) 
                bestVal = nextCost;

            tryUpdate(link, columnIdx, preStateID, nextStateID, nextCost);
        }
    }

    //
    // non-emit state inner forward
    //
    // it is a columnIdx -> columnIdx forward
    //
    // TODO : should i flood fill ?

    // 这里因为non-emit之间的forward只能用旧值,不能用nonemit forward过来的值去更新另一个non-emit, 因此要用另一个link存旧值
    // 但本质上是 同一时间t的forward操作
    for(int noEmitStateID = 0; noEmitStateID < N_States; noEmitStateID ++) {
        link[preIdx].nodes[noEmitStateID] = link[rollIdx].nodes[noEmitStateID];
    }

    for(int noEmitStateID = 0; noEmitStateID < N_States; noEmitStateID ++) {
        Dtw_Column_Node & dtw_node = link[preIdx].nodes[noEmitStateID];

        // dont forward from non-value state
        if(dtw_node.lastUpdate < columnIdx)
            continue;

        double preCost = dtw_node.cost;
        double nextCost;

        // preStateID --- nonEmitEdges[eID] ---> nextStateID
        for(int eID = states[noEmitStateID].noEmitHead; eID != NIL_EDGE; eID = nonEmitEdges[eID].next) {
            nextStateID = nonEmitEdges[eID].to;

            // penalty
            nextCost = preCost + nonEmitEdges[eID].cost;

            tryUpdate(link, columnIdx, noEmitStateID, nextStateID, nextCost);
        }
    }

    return bestVal;
}