audio-helpers.c 3.6 KB

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