示例#1
0
文件: API.cpp 项目: ChaosPower/OBS
bool OBS::SetScene(CTSTR lpScene)
{
    if(bDisableSceneSwitching)
        return false;

    HWND hwndScenes = GetDlgItem(hwndMain, ID_SCENES);
    UINT curSel = (UINT)SendMessage(hwndScenes, LB_GETCURSEL, 0, 0);

    //-------------------------

    if(curSel != LB_ERR)
    {
        UINT textLen = (UINT)SendMessage(hwndScenes, LB_GETTEXTLEN, curSel, 0);

        String strLBName;
        strLBName.SetLength(textLen);

        SendMessage(hwndScenes, LB_GETTEXT, curSel, (LPARAM)strLBName.Array());
        if(!strLBName.CompareI(lpScene))
        {
            UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
            if(id == LB_ERR)
                return false;

            SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
        }
    }
    else
    {
        UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
        if(id == LB_ERR)
            return false;

        SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
    }

    //-------------------------

    XElement *scenes = scenesConfig.GetElement(TEXT("scenes"));
    XElement *newSceneElement = scenes->GetElement(lpScene);
    if(!newSceneElement)
        return false;

    if(sceneElement == newSceneElement)
        return true;

    sceneElement = newSceneElement;

    CTSTR lpClass = sceneElement->GetString(TEXT("class"));
    if(!lpClass)
    {
        AppWarning(TEXT("OBS::SetScene: no class found for scene '%s'"), newSceneElement->GetName());
        return false;
    }

    DWORD sceneChangeStartTime;

    if(bRunning)
    {
        Log(TEXT("++++++++++++++++++++++++++++++++++++++++++++++++++++++"));
        Log(TEXT("  New Scene"));

        sceneChangeStartTime = OSGetTime();
    }

    XElement *sceneData = newSceneElement->GetElement(TEXT("data"));

    //-------------------------

    Scene *newScene = NULL;
    if(bRunning)
        newScene = CreateScene(lpClass, sceneData);

    //-------------------------

    HWND hwndSources = GetDlgItem(hwndMain, ID_SOURCES);

    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM) 0);

    App->scaleItem = NULL;

    bChangingSources = true;
    ListView_DeleteAllItems(hwndSources);

    bool bSkipTransition = false;

    XElement *sources = sceneElement->GetElement(TEXT("sources"));
    if(sources)
    {
        UINT numSources = sources->NumElements();
        ListView_SetItemCount(hwndSources, numSources);

        for(UINT i=0; i<numSources; i++)
        {
            XElement *sourceElement = sources->GetElementByID(i);
            String className = sourceElement->GetString(TEXT("class"));

            if(className == "DeviceCapture") {
                // There's a capture device in the next scene that isn't a global source,
                // so let's skip the transition since it won't work anyway.
                bSkipTransition = true;
            }
        }

        for(UINT i=0; i<numSources; i++)
        {
            XElement *sourceElement = sources->GetElementByID(i);
            bool render = sourceElement->GetInt(TEXT("render"), 1) > 0;

            InsertSourceItem(i, (LPWSTR)sourceElement->GetName(), render);

            // Do not add image sources yet in case we're skipping the transition.
            // This fixes the issue where capture devices sources that used the
            // same device as one in the previous scene would just go blank
            // after switching.
            if(bRunning && newScene && !bSkipTransition)
                newScene->AddImageSource(sourceElement);
        }
    }

    bChangingSources = false;
    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM) 0);
    RedrawWindow(hwndSources, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);

    if(scene && newScene && newScene->HasMissingSources())
        MessageBox(hwndMain, Str("Scene.MissingSources"), NULL, 0);

    if(bRunning)
    {
        //todo: cache scenes maybe?  undecided.  not really as necessary with global sources
        OSEnterMutex(hSceneMutex);

        UINT numSources;

        if (scene)
        {
            //shutdown previous scene, if any
            numSources = scene->sceneItems.Num();
            for(UINT i=0; i<numSources; i++)
            {
                XElement *source = scene->sceneItems[i]->GetElement();
                String className = source->GetString(TEXT("class"));
                if(scene->sceneItems[i]->bRender && className == "GlobalSource") {
                    XElement *globalSourceData = source->GetElement(TEXT("data"));
                    String globalSourceName = globalSourceData->GetString(TEXT("name"));
                    if(App->GetGlobalSource(globalSourceName) != NULL) {
                        App->GetGlobalSource(globalSourceName)->GlobalSourceLeaveScene();
                    }
                }
            }

            scene->EndScene();
        }

        Scene *previousScene = scene;
        scene = newScene;

        if(newScene && bSkipTransition) {
            // If we're skipping the transition because of a non-global
            // DirectShow device, delete the scene here and add the
            // ImageSources at this point instead.
            delete previousScene;

            if(sources)
            {
                UINT numSources = sources->NumElements();

                for(UINT i=0; i<numSources; i++)
                {
                    XElement *sourceElement = sources->GetElementByID(i);

                    if(newScene)
                        newScene->AddImageSource(sourceElement);
                }
            }
        }

        scene->BeginScene();

        numSources = scene->sceneItems.Num();
        for(UINT i=0; i<numSources; i++)
        {
            XElement *source = scene->sceneItems[i]->GetElement();

            String className = source->GetString(TEXT("class"));
            if(scene->sceneItems[i]->bRender && className == "GlobalSource") {
                XElement *globalSourceData = source->GetElement(TEXT("data"));
                String globalSourceName = globalSourceData->GetString(TEXT("name"));
                if(App->GetGlobalSource(globalSourceName) != NULL) {
                    App->GetGlobalSource(globalSourceName)->GlobalSourceEnterScene();
                }
            }
        }

        if(!bTransitioning && !bSkipTransition)
        {
            bTransitioning = true;
            transitionAlpha = 0.0f;
        }

        OSLeaveMutex(hSceneMutex);

        if(!bSkipTransition) {
            // Do not delete the previous scene here, since it has already
            // been deleted.
            delete previousScene;
        }

        DWORD sceneChangeTime = OSGetTime() - sceneChangeStartTime;
        if (sceneChangeTime >= 500)
            Log(TEXT("PERFORMANCE WARNING: Scene change took %u ms, maybe some sources should be global sources?"), sceneChangeTime);
    }

    if(API != NULL)
       ReportSwitchScenes(lpScene);

    return true;
}
示例#2
0
文件: API.cpp 项目: aharrison/OBS
bool OBS::SetScene(CTSTR lpScene)
{
    if(bDisableSceneSwitching)
        return false;

    HWND hwndScenes = GetDlgItem(hwndMain, ID_SCENES);
    UINT curSel = (UINT)SendMessage(hwndScenes, LB_GETCURSEL, 0, 0);

    //-------------------------

    if(curSel != LB_ERR)
    {
        UINT textLen = (UINT)SendMessage(hwndScenes, LB_GETTEXTLEN, curSel, 0);

        String strLBName;
        strLBName.SetLength(textLen);

        SendMessage(hwndScenes, LB_GETTEXT, curSel, (LPARAM)strLBName.Array());
        if(!strLBName.CompareI(lpScene))
        {
            UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
            if(id == LB_ERR)
                return false;

            SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
        }
    }
    else
    {
        UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
        if(id == LB_ERR)
            return false;

        SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
    }

    //-------------------------

    XElement *scenes = scenesConfig.GetElement(TEXT("scenes"));
    XElement *newSceneElement = scenes->GetElement(lpScene);
    if(!newSceneElement)
        return false;

    if(sceneElement == newSceneElement)
        return true;

    sceneElement = newSceneElement;

    CTSTR lpClass = sceneElement->GetString(TEXT("class"));
    if(!lpClass)
    {
        AppWarning(TEXT("OBS::SetScene: no class found for scene '%s'"), newSceneElement->GetName());
        return false;
    }

    if(bRunning)
    {
        Log(TEXT("++++++++++++++++++++++++++++++++++++++++++++++++++++++"));
        Log(TEXT("  New Scene"));
    }

    XElement *sceneData = newSceneElement->GetElement(TEXT("data"));

    //-------------------------

    Scene *newScene = NULL;
    if(bRunning)
        newScene = CreateScene(lpClass, sceneData);

    //-------------------------

    HWND hwndSources = GetDlgItem(hwndMain, ID_SOURCES);

    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM) 0);

    bChangingSources = true;
    ListView_DeleteAllItems(hwndSources);
    
    XElement *sources = sceneElement->GetElement(TEXT("sources"));
    if(sources)
    {
        UINT numSources = sources->NumElements();
        ListView_SetItemCount(hwndSources, numSources);

        for(UINT i=0; i<numSources; i++)
        {
            XElement *sourceElement = sources->GetElementByID(i);
            bool render = sourceElement->GetInt(TEXT("render"), 1) > 0;
            
            
            AddSourceItem((LPWSTR)sourceElement->GetName(), render, i);
            
           
            if(bRunning && newScene)
                newScene->AddImageSource(sourceElement);
        }
    }
    bChangingSources = false;
    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM) 0);
    RedrawWindow(hwndSources, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
    
    if(scene && newScene->HasMissingSources())
        MessageBox(hwndMain, Str("Scene.MissingSources"), NULL, 0);

    if(bRunning)
    {
        //todo: cache scenes maybe?  undecided.  not really as necessary with global sources
        OSEnterMutex(hSceneMutex);

        if(scene)
            scene->EndScene();

        Scene *previousScene = scene;
        scene = newScene;

        scene->BeginScene();

        if(!bTransitioning)
        {
            bTransitioning = true;
            transitionAlpha = 0.0f;
        }

        OSLeaveMutex(hSceneMutex);

        delete previousScene;
    }

    return true;
}
示例#3
0
文件: API.cpp 项目: Crimson13/OBS
bool OBS::SetScene(CTSTR lpScene)
{
    if(bDisableSceneSwitching)
        return false;

    HWND hwndScenes = GetDlgItem(hwndMain, ID_SCENES);
    UINT curSel = (UINT)SendMessage(hwndScenes, LB_GETCURSEL, 0, 0);

    //-------------------------

    if(curSel != LB_ERR)
    {
        UINT textLen = (UINT)SendMessage(hwndScenes, LB_GETTEXTLEN, curSel, 0);

        String strLBName;
        strLBName.SetLength(textLen);

        SendMessage(hwndScenes, LB_GETTEXT, curSel, (LPARAM)strLBName.Array());
        if(!strLBName.CompareI(lpScene))
        {
            UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
            if(id == LB_ERR)
                return false;

            SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
        }
    }
    else
    {
        UINT id = (UINT)SendMessage(hwndScenes, LB_FINDSTRINGEXACT, -1, (LPARAM)lpScene);
        if(id == LB_ERR)
            return false;

        SendMessage(hwndScenes, LB_SETCURSEL, id, 0);
    }

    //-------------------------

    XElement *scenes = scenesConfig.GetElement(TEXT("scenes"));
    XElement *newSceneElement = scenes->GetElement(lpScene);
    if(!newSceneElement)
        return false;

    if(sceneElement == newSceneElement)
        return true;

    sceneElement = newSceneElement;

    CTSTR lpClass = sceneElement->GetString(TEXT("class"));
    if(!lpClass)
    {
        AppWarning(TEXT("OBS::SetScene: no class found for scene '%s'"), newSceneElement->GetName());
        return false;
    }

    DWORD sceneChangeStartTime;

    if(bRunning)
    {
        Log(TEXT("++++++++++++++++++++++++++++++++++++++++++++++++++++++"));
        Log(TEXT("  New Scene"));

        sceneChangeStartTime = OSGetTime();
    }

    XElement *sceneData = newSceneElement->GetElement(TEXT("data"));

    //-------------------------

    Scene *newScene = NULL;
    if(bRunning)
        newScene = CreateScene(lpClass, sceneData);

    //-------------------------

    HWND hwndSources = GetDlgItem(hwndMain, ID_SOURCES);

    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM) 0);

    bChangingSources = true;
    ListView_DeleteAllItems(hwndSources);

    XElement *sources = sceneElement->GetElement(TEXT("sources"));
    if(sources)
    {
        UINT numSources = sources->NumElements();
        ListView_SetItemCount(hwndSources, numSources);

        for(UINT i=0; i<numSources; i++)
        {
            XElement *sourceElement = sources->GetElementByID(i);
            bool render = sourceElement->GetInt(TEXT("render"), 1) > 0;

            InsertSourceItem(i, (LPWSTR)sourceElement->GetName(), render);

            if(bRunning && newScene)
                newScene->AddImageSource(sourceElement);
        }
    }

    bChangingSources = false;
    SendMessage(hwndSources, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM) 0);
    RedrawWindow(hwndSources, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);

    if(scene && newScene && newScene->HasMissingSources())
        MessageBox(hwndMain, Str("Scene.MissingSources"), NULL, 0);

    if(bRunning)
    {
        //todo: cache scenes maybe?  undecided.  not really as necessary with global sources
        OSEnterMutex(hSceneMutex);

        UINT numSources;

        if (scene)
        {
            //shutdown previous scene, if any
            numSources = scene->sceneItems.Num();
            for(UINT i=0; i<numSources; i++)
            {
                XElement *source = scene->sceneItems[i]->GetElement();
                String className = source->GetString(TEXT("class"));
                if(scene->sceneItems[i]->bRender && className == "GlobalSource") {
                    XElement *globalSourceData = source->GetElement(TEXT("data"));
                    String globalSourceName = globalSourceData->GetString(TEXT("name"));
                    if(App->GetGlobalSource(globalSourceName) != NULL) {
                        App->GetGlobalSource(globalSourceName)->GlobalSourceLeaveScene();
                    }
                }
            }

            scene->EndScene();
        }

        Scene *previousScene = scene;
        scene = newScene;

        scene->BeginScene();

        numSources = scene->sceneItems.Num();
        for(UINT i=0; i<numSources; i++)
        {
            XElement *source = scene->sceneItems[i]->GetElement();
            String className = source->GetString(TEXT("class"));
            if(scene->sceneItems[i]->bRender && className == "GlobalSource") {
                XElement *globalSourceData = source->GetElement(TEXT("data"));
                String globalSourceName = globalSourceData->GetString(TEXT("name"));
                if(App->GetGlobalSource(globalSourceName) != NULL) {
                    App->GetGlobalSource(globalSourceName)->GlobalSourceEnterScene();
                }
            }
        }

        if(!bTransitioning)
        {
            bTransitioning = true;
            transitionAlpha = 0.0f;
        }

        OSLeaveMutex(hSceneMutex);

        delete previousScene;

        DWORD sceneChangeTime = OSGetTime() - sceneChangeStartTime;
        if (sceneChangeTime >= 500)
            Log(TEXT("PERFORMANCE WARNING: Scene change took %u ms, maybe some sources should be global sources?"), sceneChangeTime);
    }

    if(API != NULL)
       ReportSwitchScenes(lpScene);

    return true;
}