test.mm 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <functional>
  4. #include <memory>
  5. #import <Cocoa/Cocoa.h>
  6. #import <AppKit/AppKit.h>
  7. #import <OpenGL/OpenGL.h>
  8. #include <util/base.h>
  9. #include <obs.h>
  10. static const int cx = 800;
  11. static const int cy = 600;
  12. /* --------------------------------------------------- */
  13. template<typename T, typename D_T, D_T D>
  14. struct OBSUniqueHandle : std::unique_ptr<T, std::function<D_T>> {
  15. using base = std::unique_ptr<T, std::function<D_T>>;
  16. explicit OBSUniqueHandle(T *obj = nullptr) : base(obj, D) {}
  17. operator T *() { return base::get(); }
  18. };
  19. #define DECLARE_DELETER(x) decltype(x), x
  20. using SourceContext =
  21. OBSUniqueHandle<obs_source, DECLARE_DELETER(obs_source_release)>;
  22. using SceneContext =
  23. OBSUniqueHandle<obs_scene, DECLARE_DELETER(obs_scene_release)>;
  24. using DisplayContext =
  25. OBSUniqueHandle<obs_display, DECLARE_DELETER(obs_display_destroy)>;
  26. #undef DECLARE_DELETER
  27. /* --------------------------------------------------- */
  28. static void CreateOBS()
  29. {
  30. if (!obs_startup("en", nullptr))
  31. throw "Couldn't create OBS";
  32. struct obs_video_info ovi;
  33. ovi.adapter = 0;
  34. ovi.fps_num = 30000;
  35. ovi.fps_den = 1001;
  36. ovi.graphics_module = DL_OPENGL;
  37. ovi.output_format = VIDEO_FORMAT_RGBA;
  38. ovi.base_width = cx;
  39. ovi.base_height = cy;
  40. ovi.output_width = cx;
  41. ovi.output_height = cy;
  42. if (obs_reset_video(&ovi) != 0)
  43. throw "Couldn't initialize video";
  44. }
  45. static DisplayContext CreateDisplay(NSView *view)
  46. {
  47. gs_init_data info = {};
  48. info.cx = cx;
  49. info.cy = cy;
  50. info.format = GS_RGBA;
  51. info.zsformat = GS_ZS_NONE;
  52. info.window.view = view;
  53. return DisplayContext{obs_display_create(&info)};
  54. }
  55. static SceneContext SetupScene()
  56. {
  57. /* ------------------------------------------------------ */
  58. /* load modules */
  59. obs_load_all_modules();
  60. /* ------------------------------------------------------ */
  61. /* create source */
  62. SourceContext source{
  63. obs_source_create("random", "a test source", nullptr, nullptr)};
  64. if (!source)
  65. throw "Couldn't create random test source";
  66. /* ------------------------------------------------------ */
  67. /* create scene and add source to scene */
  68. SceneContext scene{obs_scene_create("test scene")};
  69. if (!scene)
  70. throw "Couldn't create scene";
  71. obs_scene_add(scene, source);
  72. /* ------------------------------------------------------ */
  73. /* set the scene as the primary draw source and go */
  74. obs_set_output_source(0, obs_scene_get_source(scene));
  75. return scene;
  76. }
  77. @interface OBSTest : NSObject <NSApplicationDelegate, NSWindowDelegate> {
  78. NSWindow *win;
  79. NSView *view;
  80. DisplayContext display;
  81. SceneContext scene;
  82. }
  83. - (void)applicationDidFinishLaunching:(NSNotification *)notification;
  84. - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app;
  85. - (void)windowWillClose:(NSNotification *)notification;
  86. @end
  87. @implementation OBSTest
  88. - (void)applicationDidFinishLaunching:(NSNotification *)notification
  89. {
  90. UNUSED_PARAMETER(notification);
  91. try {
  92. NSRect content_rect = NSMakeRect(0, 0, cx, cy);
  93. win = [[NSWindow alloc]
  94. initWithContentRect:content_rect
  95. styleMask:NSTitledWindowMask |
  96. NSClosableWindowMask
  97. backing:NSBackingStoreBuffered
  98. defer:NO];
  99. if (!win)
  100. throw "Could not create window";
  101. view = [[NSView alloc] initWithFrame:content_rect];
  102. if (!view)
  103. throw "Could not create view";
  104. CreateOBS();
  105. win.title = @"foo";
  106. win.delegate = self;
  107. win.contentView = view;
  108. [win orderFrontRegardless];
  109. [win center];
  110. [win makeMainWindow];
  111. display = CreateDisplay(view);
  112. scene = SetupScene();
  113. obs_display_add_draw_callback(
  114. display.get(),
  115. [](void *, uint32_t, uint32_t) {
  116. obs_render_main_texture();
  117. },
  118. nullptr);
  119. } catch (char const *error) {
  120. NSLog(@"%s\n", error);
  121. [NSApp terminate:nil];
  122. }
  123. }
  124. - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
  125. {
  126. UNUSED_PARAMETER(app);
  127. return YES;
  128. }
  129. - (void)windowWillClose:(NSNotification *)notification
  130. {
  131. UNUSED_PARAMETER(notification);
  132. obs_set_output_source(0, nullptr);
  133. scene.reset();
  134. display.reset();
  135. obs_shutdown();
  136. NSLog(@"Number of memory leaks: %lu", bnum_allocs());
  137. }
  138. @end
  139. /* --------------------------------------------------- */
  140. int main()
  141. {
  142. @autoreleasepool {
  143. NSApplication *app = [NSApplication sharedApplication];
  144. OBSTest *test = [[OBSTest alloc] init];
  145. app.delegate = test;
  146. [app run];
  147. }
  148. return 0;
  149. }