test.mm 4.4 KB

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