test.mm 4.7 KB

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