monitor-capture.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include <util/dstr.h>
  2. #include "dc-capture.h"
  3. struct monitor_capture {
  4. obs_source_t source;
  5. int monitor;
  6. bool capture_cursor;
  7. bool compatibility;
  8. struct dc_capture data;
  9. effect_t opaque_effect;
  10. };
  11. struct monitor_info {
  12. int cur_id;
  13. int desired_id;
  14. int id;
  15. RECT rect;
  16. };
  17. /* ------------------------------------------------------------------------- */
  18. static inline void do_log(int level, const char *msg, ...)
  19. {
  20. va_list args;
  21. struct dstr str = {0};
  22. va_start(args, msg);
  23. dstr_copy(&str, "[GDI monitor capture]: ");
  24. dstr_vcatf(&str, msg, args);
  25. blog(level, "%s", str.array);
  26. dstr_free(&str);
  27. va_end(args);
  28. }
  29. static BOOL CALLBACK enum_monitor(HMONITOR handle, HDC hdc, LPRECT rect,
  30. LPARAM param)
  31. {
  32. struct monitor_info *monitor = (struct monitor_info *)param;
  33. if (monitor->cur_id == 0 || monitor->desired_id == monitor->cur_id) {
  34. monitor->rect = *rect;
  35. monitor->id = monitor->cur_id;
  36. }
  37. return (monitor->desired_id < monitor->cur_id++);
  38. }
  39. static void update_monitor(struct monitor_capture *capture,
  40. obs_data_t settings)
  41. {
  42. struct monitor_info monitor = {0};
  43. uint32_t width, height;
  44. monitor.desired_id = (int)obs_data_getint(settings, "monitor");
  45. EnumDisplayMonitors(NULL, NULL, enum_monitor, (LPARAM)&monitor);
  46. capture->monitor = monitor.id;
  47. width = monitor.rect.right - monitor.rect.left;
  48. height = monitor.rect.bottom - monitor.rect.top;
  49. dc_capture_init(&capture->data, monitor.rect.left, monitor.rect.top,
  50. width, height, capture->capture_cursor,
  51. capture->compatibility);
  52. }
  53. static inline void update_settings(struct monitor_capture *capture,
  54. obs_data_t settings)
  55. {
  56. capture->capture_cursor = obs_data_getbool(settings, "capture_cursor");
  57. capture->compatibility = obs_data_getbool(settings, "compatibility");
  58. dc_capture_free(&capture->data);
  59. update_monitor(capture, settings);
  60. }
  61. /* ------------------------------------------------------------------------- */
  62. static const char *monitor_capture_getname(const char *locale)
  63. {
  64. /* TODO: translate */
  65. return "Monitor Capture";
  66. }
  67. static void monitor_capture_destroy(void *data)
  68. {
  69. struct monitor_capture *capture = data;
  70. gs_entercontext(obs_graphics());
  71. dc_capture_free(&capture->data);
  72. effect_destroy(capture->opaque_effect);
  73. gs_leavecontext();
  74. bfree(capture);
  75. }
  76. static void monitor_capture_defaults(obs_data_t settings)
  77. {
  78. obs_data_set_default_int(settings, "monitor", 0);
  79. obs_data_set_default_bool(settings, "capture_cursor", true);
  80. obs_data_set_default_bool(settings, "compatibility", false);
  81. }
  82. static void *monitor_capture_create(obs_data_t settings, obs_source_t source)
  83. {
  84. struct monitor_capture *capture;
  85. effect_t opaque_effect = create_opaque_effect();
  86. if (!opaque_effect)
  87. return NULL;
  88. capture = bzalloc(sizeof(struct monitor_capture));
  89. capture->opaque_effect = opaque_effect;
  90. update_settings(capture, settings);
  91. return capture;
  92. }
  93. static void monitor_capture_tick(void *data, float seconds)
  94. {
  95. struct monitor_capture *capture = data;
  96. gs_entercontext(obs_graphics());
  97. dc_capture_capture(&capture->data, NULL);
  98. gs_leavecontext();
  99. UNUSED_PARAMETER(seconds);
  100. }
  101. static void monitor_capture_render(void *data, effect_t effect)
  102. {
  103. struct monitor_capture *capture = data;
  104. dc_capture_render(&capture->data, capture->opaque_effect);
  105. }
  106. static uint32_t monitor_capture_width(void *data)
  107. {
  108. struct monitor_capture *capture = data;
  109. return capture->data.width;
  110. }
  111. static uint32_t monitor_capture_height(void *data)
  112. {
  113. struct monitor_capture *capture = data;
  114. return capture->data.height;
  115. }
  116. struct obs_source_info monitor_capture_info = {
  117. .id = "monitor_capture",
  118. .type = OBS_SOURCE_TYPE_INPUT,
  119. .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
  120. .getname = monitor_capture_getname,
  121. .create = monitor_capture_create,
  122. .destroy = monitor_capture_destroy,
  123. .getwidth = monitor_capture_width,
  124. .getheight = monitor_capture_height,
  125. .defaults = monitor_capture_defaults,
  126. .video_render = monitor_capture_render,
  127. .video_tick = monitor_capture_tick
  128. };