Skip to content

Conversation

@dsaedtler
Copy link
Contributor

Description

Changes the saving logic a bit so that scenes from canvases not managed by the frontend won't get saved.

Also refactors the saving a bit since the separate GenerateSaveData() seems unnecessary.

Motivation and Context

The intention was that the frontend should only save and load canvases it manages (i.e. created via the frontend API). Likewise it shouldn't save any scenes on canvases that aren't frontend-managed or ephemeral.

This problem was reported on Discord.

How Has This Been Tested?

Saved and loaded some scene collections.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Tweak (non-breaking change to improve existing functionality)
  • Code cleanup (non-breaking change which makes code smaller or more readable)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@WizardCM WizardCM added Bug Fix Non-breaking change which fixes an issue Enhancement Improvement to existing functionality Code Cleanup Non-breaking change which makes code smaller or more readable labels Oct 4, 2025
Comment on lines +70 to +75
#define DESKTOP_AUDIO_1 "DesktopAudioDevice1"
#define DESKTOP_AUDIO_2 "DesktopAudioDevice2"
#define AUX_AUDIO_1 "AuxAudioDevice1"
#define AUX_AUDIO_2 "AuxAudioDevice2"
#define AUX_AUDIO_3 "AuxAudioDevice3"
#define AUX_AUDIO_4 "AuxAudioDevice4"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're changing this, we might as well make those proper static constexpr std::string_views and update SaveAudioDevice appropriately, moving it into the anonymous namespace instead of using the static storage identifier, and only reaching into the char pointer at the boundary to the C API.

obs_data_t *saveData = obs_data_create();
OBSDataAutoRelease saveData = obs_data_create();

/* Scene collection name */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use C++ comment style in C++ source code. The PR seems to mix both styles.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old habits die hard!


/* -------------------------------- */
/* save group sources separately */
// We're saving groups separately ensures they won't be loaded in older versions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We're saving groups separately ensures they won't be loaded in older versions.
// Saving groups separately ensures they won't be loaded in older versions.

/* -------------------------------- */
/* save group sources separately */
// We're saving groups separately ensures they won't be loaded in older versions.
// ToDo: Get rid of this at some point. Groups were introduced in 22.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// ToDo: Get rid of this at some point. Groups were introduced in 22.0
// TODO: Get rid of this at some point. Groups were introduced in 22.0

All caps should be most compatible with language servers and IDEs.

obs_data_set_array(saveData, "transitions", transitions);
obs_data_set_array(saveData, "saved_projectors", savedProjectorList);
obs_data_set_array(saveData, "canvases", savedCanvases);
// Iterate over our additional canvases (if any), save their scenes and groups.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a distinction in code between the "main" canvas and "additional canvases"? Wouldn't it be simpler to iterate over all canvases and save them (if they are eligible for saving), as that would include the main canvas by default anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The distinction is made because the primary/main canvas always exists and is not itself part of the frontend's canvases list (at least, not yet).

And we only iterate that list rather than all canvases because we only want to save the scenes associated with frontend-managed canvases (i.e. ones that were created via the frontend API and are tracked in canvases), not any other ones that may have been created with libobs directly, e.g. by third-party plugins.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right so the "main" canvas still represents "the" scene collection, and canvases exist on top of that. Otherwise we'd need a "scene collection v3" that is built on top of a list of canvases as its "root" object?

using sourcesAndGroups_t = decltype(sourcesAndGroups);

/* -------------------------------- */
auto sceneSaveCallback = [](void *param, obs_source_t *source) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a "save" callback, because it doesn't save anything. It only gets source and group data, so exportSceneItemsCallback would be more appropriate IMO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Fix Non-breaking change which fixes an issue Code Cleanup Non-breaking change which makes code smaller or more readable Enhancement Improvement to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants