test.mm 4.7 KB

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