Handle source adding/removal better

- Made it so that when a source is added or removed from a scene it
   will add a reference to sourceSceneRefs (std::unordered_map).  Each
   source adds a reference to that every time they are added to a scene,
   and releases a reference from it when they are removed from a scene.

   When the value reaches 0, the source is no longer in any scenes, and
   is then marked for removal and destroyed.

   Before, I was using the source internal reference counter, which is a
   really bad thing to do because I don't know what might actually be
   referencing it.  So using a separate discrete reference counter for
   the number of scenes it's in is better in this case.
This commit is contained in:
jp9000 2014-01-06 20:20:18 -07:00
parent 509a3481da
commit 4fe3c47216
2 changed files with 43 additions and 19 deletions

View file

@ -54,28 +54,53 @@ void OBSBasic::RemoveScene(obs_source_t source)
const char *name = obs_source_getname(source);
int idx = scenes->FindString(name);
if (idx != wxNOT_FOUND)
int sel = scenes->GetSelection();
if (idx != wxNOT_FOUND) {
if (sel == idx)
sources->Clear();
scenes->Delete(idx);
}
}
void OBSBasic::AddSceneItem(obs_sceneitem_t item)
{
obs_scene_t scene = obs_sceneitem_getscene(item);
obs_source_t source = obs_sceneitem_getsource(item);
const char *name = obs_source_getname(source);
sources->Insert(WX_UTF8(name), 0, item);
if (GetCurrentScene() == scene)
sources->Insert(WX_UTF8(name), 0, item);
sourceSceneRefs[source] = sourceSceneRefs[source] + 1;
}
void OBSBasic::RemoveSceneItem(obs_sceneitem_t item)
{
for (unsigned int idx = 0; idx < sources->GetCount(); idx++) {
obs_sceneitem_t curItem;
curItem = (obs_sceneitem_t)sources->GetClientData(idx);
obs_scene_t scene = obs_sceneitem_getscene(item);
if (item == curItem) {
sources->Delete(idx);
break;
if (GetCurrentScene() == scene) {
for (unsigned int idx = 0; idx < sources->GetCount(); idx++) {
obs_sceneitem_t curItem;
curItem = (obs_sceneitem_t)sources->GetClientData(idx);
if (item == curItem) {
sources->Delete(idx);
break;
}
}
}
obs_source_t source = obs_sceneitem_getsource(item);
obs_source_addref(source);
obs_source_release(source);
int scenes = sourceSceneRefs[source] - 1;
if (scenes == 0) {
obs_source_remove(source);
sourceSceneRefs.erase(source);
}
}
void OBSBasic::UpdateSources(obs_scene_t scene)
@ -122,8 +147,7 @@ void OBSBasic::SceneItemAdded(void *data, calldata_t params)
obs_scene_t scene = (obs_scene_t)calldata_ptr(params, "scene");
obs_sceneitem_t item = (obs_sceneitem_t)calldata_ptr(params, "item");
if (window->GetCurrentScene() == scene)
window->AddSceneItem(item);
window->AddSceneItem(item);
}
void OBSBasic::SceneItemRemoved(void *data, calldata_t params)
@ -133,8 +157,7 @@ void OBSBasic::SceneItemRemoved(void *data, calldata_t params)
obs_scene_t scene = (obs_scene_t)calldata_ptr(params, "scene");
obs_sceneitem_t item = (obs_sceneitem_t)calldata_ptr(params, "item");
if (window->GetCurrentScene() == scene)
window->RemoveSceneItem(item);
window->RemoveSceneItem(item);
}
void OBSBasic::SourceAdded(void *data, calldata_t params)
@ -408,6 +431,9 @@ void OBSBasic::AddSource(obs_scene_t scene, const char *id)
if (success) {
obs_source_t source = obs_source_create(SOURCE_INPUT, id,
name.c_str(), NULL);
sourceSceneRefs[source] = 0;
obs_add_source(source);
obs_sceneitem_t item = obs_scene_add(scene, source);
obs_source_release(source);
@ -460,13 +486,7 @@ void OBSBasic::sourceRemoveClicked(wxCommandEvent &event)
obs_sceneitem_t item = (obs_sceneitem_t)sources->GetClientData(sel);
obs_source_t source = obs_sceneitem_getsource(item);
int ref = obs_sceneitem_destroy(item);
/* If this is the last reference in the scene, mark the source for
* removal. Reference count being at 1 means that it's no longer in
* any more scenes. */
if (ref == 1)
obs_source_remove(source);
obs_sceneitem_destroy(item);
}
void OBSBasic::sourcePropertiesClicked(wxCommandEvent &event)

View file

@ -21,7 +21,11 @@
#include <obs.hpp>
#include <unordered_map>
class OBSBasic : public OBSBasicBase {
std::unordered_map<obs_source_t, int> sourceSceneRefs;
obs_scene_t GetCurrentScene();
void AddSceneItem(obs_sceneitem_t item);
void RemoveSceneItem(obs_sceneitem_t item);