audio-helpers.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "audio-helpers.h"
  2. #include <util/dstr.h>
  3. static inline bool settings_changed(obs_data_t *old_settings, obs_data_t *new_settings)
  4. {
  5. const char *old_window = obs_data_get_string(old_settings, "window");
  6. const char *new_window = obs_data_get_string(new_settings, "window");
  7. enum window_priority old_priority = obs_data_get_int(old_settings, "priority");
  8. enum window_priority new_priority = obs_data_get_int(new_settings, "priority");
  9. // Changes to priority only matter if a window is set
  10. return (old_priority != new_priority && *new_window) || strcmp(old_window, new_window) != 0;
  11. }
  12. static inline void reroute_wasapi_source(obs_source_t *wasapi, obs_source_t *target)
  13. {
  14. proc_handler_t *ph = obs_source_get_proc_handler(wasapi);
  15. calldata_t cd = {0};
  16. calldata_set_ptr(&cd, "target", target);
  17. proc_handler_call(ph, "reroute_audio", &cd);
  18. calldata_free(&cd);
  19. }
  20. void setup_audio_source(obs_source_t *parent, obs_source_t **child, const char *window, bool enabled,
  21. enum window_priority priority)
  22. {
  23. if (enabled) {
  24. obs_data_t *wasapi_settings = NULL;
  25. if (window) {
  26. wasapi_settings = obs_data_create();
  27. obs_data_set_string(wasapi_settings, "window", window);
  28. obs_data_set_int(wasapi_settings, "priority", priority);
  29. }
  30. if (!*child) {
  31. struct dstr name = {0};
  32. dstr_printf(&name, "%s (%s)", obs_source_get_name(parent), TEXT_CAPTURE_AUDIO_SUFFIX);
  33. *child = obs_source_create_private(AUDIO_SOURCE_TYPE, name.array, wasapi_settings);
  34. // Ensure child gets activated/deactivated properly
  35. obs_source_add_active_child(parent, *child);
  36. // Reroute audio to come from window/game capture source
  37. reroute_wasapi_source(*child, parent);
  38. // Show source in mixer
  39. obs_source_set_audio_active(parent, true);
  40. dstr_free(&name);
  41. } else if (wasapi_settings) {
  42. obs_data_t *old_settings = obs_source_get_settings(*child);
  43. // Only bother updating if settings changed
  44. if (settings_changed(old_settings, wasapi_settings))
  45. obs_source_update(*child, wasapi_settings);
  46. obs_data_release(old_settings);
  47. }
  48. obs_data_release(wasapi_settings);
  49. } else {
  50. obs_source_set_audio_active(parent, false);
  51. if (*child) {
  52. reroute_wasapi_source(*child, NULL);
  53. obs_source_remove_active_child(parent, *child);
  54. obs_source_release(*child);
  55. *child = NULL;
  56. }
  57. }
  58. }
  59. static inline void encode_dstr(struct dstr *str)
  60. {
  61. dstr_replace(str, "#", "#22");
  62. dstr_replace(str, ":", "#3A");
  63. }
  64. void reconfigure_audio_source(obs_source_t *source, HWND window)
  65. {
  66. struct dstr title = {0};
  67. struct dstr class = {0};
  68. struct dstr exe = {0};
  69. struct dstr encoded = {0};
  70. ms_get_window_title(&title, window);
  71. ms_get_window_class(&class, window);
  72. ms_get_window_exe(&exe, window);
  73. encode_dstr(&title);
  74. encode_dstr(&class);
  75. encode_dstr(&exe);
  76. dstr_cat_dstr(&encoded, &title);
  77. dstr_cat(&encoded, ":");
  78. dstr_cat_dstr(&encoded, &class);
  79. dstr_cat(&encoded, ":");
  80. dstr_cat_dstr(&encoded, &exe);
  81. obs_data_t *audio_settings = obs_data_create();
  82. obs_data_set_string(audio_settings, "window", encoded.array);
  83. obs_data_set_int(audio_settings, "priority", WINDOW_PRIORITY_CLASS);
  84. obs_source_update(source, audio_settings);
  85. obs_data_release(audio_settings);
  86. dstr_free(&encoded);
  87. dstr_free(&title);
  88. dstr_free(&class);
  89. dstr_free(&exe);
  90. }
  91. void rename_audio_source(void *param, calldata_t *data)
  92. {
  93. obs_source_t *src = *(obs_source_t **)param;
  94. if (!src)
  95. return;
  96. struct dstr name = {0};
  97. dstr_printf(&name, "%s (%s)", calldata_string(data, "new_name"), TEXT_CAPTURE_AUDIO_SUFFIX);
  98. obs_source_set_name(src, name.array);
  99. dstr_free(&name);
  100. }