Add preliminary saving/loading of scene/sources

This saves scenes/sources from json on exit, and properly loads it back
up when starting up the program again, as well as the currently active
scene.

I had to add a 'load' and 'save' callback to the source interface
structure because I realizes that certain sources (such as scenes)
operate different with their saved data; scenes for example would have
to keep track of their settings information constantly, and that was
somewhat unacceptable to make it functional.

The optional 'load' callback will be called only after having loaded
setttings specifically from file/imported data, and the 'save' function
will be called only specifically when data actually needs to be saved.

I also had to adjust the obs_scene code so that it's a regular input
source type now, and I also modified it so that it doesn't have some
strange custom creation code anymore.  The obs_scene_create function is
now simply just a wrapper for obs_source_create.  You could even create
a scene with obs_source_create manually as well.
This commit is contained in:
jp9000
2014-04-26 23:47:50 -07:00
parent 21b67d007b
commit 65455c27be
7 changed files with 314 additions and 56 deletions

View File

@@ -66,6 +66,59 @@ OBSBasic::OBSBasic(QWidget *parent)
});
}
static obs_data_t GenerateSaveData()
{
obs_data_t saveData = obs_data_create();
obs_data_array_t sourcesArray = obs_save_sources();
obs_source_t currentScene = obs_get_output_source(0);
const char *sceneName = obs_source_getname(currentScene);
obs_data_setstring(saveData, "current_scene", sceneName);
obs_data_setarray(saveData, "sources", sourcesArray);
obs_data_array_release(sourcesArray);
obs_source_release(currentScene);
return saveData;
}
void OBSBasic::Save(const char *file)
{
obs_data_t saveData = GenerateSaveData();
const char *jsonData = obs_data_getjson(saveData);
/* TODO maybe a message box here? */
if (!os_quick_write_utf8_file(file, jsonData, strlen(jsonData), false))
blog(LOG_ERROR, "Could not save scene data to %s", file);
obs_data_release(saveData);
}
void OBSBasic::Load(const char *file)
{
if (!file) {
blog(LOG_ERROR, "Could not find file %s", file);
return;
}
BPtr<char> jsonData = os_quick_read_utf8_file(file);
if (!jsonData)
return;
obs_data_t data = obs_data_create_from_json(jsonData);
obs_data_array_t sources = obs_data_getarray(data, "sources");
const char *sceneName = obs_data_getstring(data, "current_scene");
obs_source_t curScene;
obs_load_sources(sources);
curScene = obs_get_source_by_name(sceneName);
obs_set_output_source(0, curScene);
obs_source_release(curScene);
obs_data_array_release(sources);
obs_data_release(data);
}
static inline bool HasAudioDevices(const char *source_id)
{
const char *output_id = source_id;
@@ -310,12 +363,17 @@ void OBSBasic::OBSInit()
if (!InitService())
throw "Failed to initialize service";
BPtr<char> savePath(os_get_config_path("obs-studio/basic/scenes.json"));
Load(savePath);
ResetAudioDevices();
}
OBSBasic::~OBSBasic()
{
BPtr<char> savePath(os_get_config_path("obs-studio/basic/scenes.json"));
SaveService();
Save(savePath);
if (properties)
delete properties;
@@ -441,12 +499,12 @@ void OBSBasic::UpdateSceneSelection(OBSSource source)
obs_source_type type;
obs_source_gettype(source, &type, NULL);
if (type != OBS_SOURCE_TYPE_SCENE)
return;
obs_scene_t scene = obs_scene_fromsource(source);
const char *name = obs_source_getname(source);
if (!scene)
return;
QList<QListWidgetItem*> items =
ui->scenes->findItems(QT_UTF8(name), Qt::MatchExactly);
@@ -486,10 +544,7 @@ void OBSBasic::SourceAdded(void *data, calldata_t params)
{
obs_source_t source = (obs_source_t)calldata_ptr(params, "source");
obs_source_type type;
obs_source_gettype(source, &type, NULL);
if (type == OBS_SOURCE_TYPE_SCENE)
if (obs_scene_fromsource(source) != NULL)
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
"AddScene",
Q_ARG(OBSSource, OBSSource(source)));
@@ -499,10 +554,7 @@ void OBSBasic::SourceRemoved(void *data, calldata_t params)
{
obs_source_t source = (obs_source_t)calldata_ptr(params, "source");
obs_source_type type;
obs_source_gettype(source, &type, NULL);
if (type == OBS_SOURCE_TYPE_SCENE)
if (obs_scene_fromsource(source) != NULL)
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
"RemoveScene",
Q_ARG(OBSSource, OBSSource(source)));
@@ -906,6 +958,9 @@ void OBSBasic::AddSourcePopupMenu(const QPoint &pos)
OBS_SOURCE_TYPE_INPUT,
type, App()->GetLocale());
if (strcmp(type, "scene") == 0)
continue;
QAction *popupItem = new QAction(QT_UTF8(name), this);
popupItem->setData(QT_UTF8(type));
popup.addAction(popupItem);

View File

@@ -52,6 +52,9 @@ private:
QPointer<OBSBasicProperties> properties;
void Save(const char *file);
void Load(const char *file);
void SaveService();
bool LoadService();