obs-app.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include <sstream>
  15. #include <util/bmem.h>
  16. #include <util/dstr.h>
  17. #include <util/platform.h>
  18. #include <obs.hpp>
  19. #include <QProxyStyle>
  20. #include "qt-wrappers.hpp"
  21. #include "obs-app.hpp"
  22. #include "window-basic-main.hpp"
  23. #include "platform.hpp"
  24. #ifdef _WIN32
  25. #include <fstream>
  26. #include <windows.h>
  27. #else
  28. #include <signal.h>
  29. #endif
  30. using namespace std;
  31. #ifdef _WIN32
  32. static void do_log(int log_level, const char *msg, va_list args, void *param)
  33. {
  34. fstream &logFile = *static_cast<fstream*>(param);
  35. char bla[4096];
  36. vsnprintf(bla, 4095, msg, args);
  37. OutputDebugStringA(bla);
  38. OutputDebugStringA("\n");
  39. if (log_level <= LOG_INFO)
  40. logFile << bla << endl;
  41. if (log_level <= LOG_ERROR && IsDebuggerPresent())
  42. __debugbreak();
  43. }
  44. #endif
  45. bool OBSApp::InitGlobalConfigDefaults()
  46. {
  47. config_set_default_string(globalConfig, "General", "Language", "en");
  48. #if _WIN32
  49. config_set_default_string(globalConfig, "Video", "Renderer",
  50. "Direct3D 11");
  51. #else
  52. config_set_default_string(globalConfig, "Video", "Renderer", "OpenGL");
  53. #endif
  54. return true;
  55. }
  56. static bool do_mkdir(const char *path)
  57. {
  58. if (os_mkdir(path) == MKDIR_ERROR) {
  59. OBSErrorBox(NULL, "Failed to create directory %s", path);
  60. return false;
  61. }
  62. return true;
  63. }
  64. static bool MakeUserDirs()
  65. {
  66. BPtr<char> configPath;
  67. configPath = os_get_config_path("obs-studio");
  68. if (!do_mkdir(configPath))
  69. return false;
  70. configPath = os_get_config_path("obs-studio/basic");
  71. if (!do_mkdir(configPath))
  72. return false;
  73. configPath = os_get_config_path("obs-studio/studio");
  74. if (!do_mkdir(configPath))
  75. return false;
  76. return true;
  77. }
  78. bool OBSApp::InitGlobalConfig()
  79. {
  80. BPtr<char> path(os_get_config_path("obs-studio/global.ini"));
  81. int errorcode = globalConfig.Open(path, CONFIG_OPEN_ALWAYS);
  82. if (errorcode != CONFIG_SUCCESS) {
  83. OBSErrorBox(NULL, "Failed to open global.ini: %d", errorcode);
  84. return false;
  85. }
  86. return InitGlobalConfigDefaults();
  87. }
  88. #define DEFAULT_LANG "en"
  89. bool OBSApp::InitLocale()
  90. {
  91. const char *lang = config_get_string(globalConfig, "General",
  92. "Language");
  93. locale = lang;
  94. stringstream file;
  95. file << "locale/" << lang << ".txt";
  96. string englishPath;
  97. if (!GetDataFilePath("locale/" DEFAULT_LANG ".txt", englishPath)) {
  98. OBSErrorBox(NULL, "Failed to find locale/" DEFAULT_LANG ".txt");
  99. return false;
  100. }
  101. textLookup = text_lookup_create(englishPath.c_str());
  102. if (!textLookup) {
  103. OBSErrorBox(NULL, "Failed to create locale from file '%s'",
  104. englishPath.c_str());
  105. return false;
  106. }
  107. if (astrcmpi(lang, DEFAULT_LANG) == 0)
  108. return true;
  109. string path;
  110. if (GetDataFilePath(file.str().c_str(), path)) {
  111. if (!text_lookup_add(textLookup, path.c_str()))
  112. blog(LOG_ERROR, "Failed to add locale file '%s'",
  113. path.c_str());
  114. } else {
  115. blog(LOG_ERROR, "Could not find locale file '%s'",
  116. file.str().c_str());
  117. }
  118. return true;
  119. }
  120. OBSApp::OBSApp(int &argc, char **argv)
  121. : QApplication(argc, argv)
  122. {
  123. if (!InitApplicationBundle())
  124. throw "Failed to initialize application bundle";
  125. if (!MakeUserDirs())
  126. throw "Failed to created required user directories";
  127. if (!InitGlobalConfig())
  128. throw "Failed to initialize global config";
  129. if (!InitLocale())
  130. throw "Failed to load locale";
  131. mainWindow = move(unique_ptr<OBSBasic>(new OBSBasic()));
  132. }
  133. const char *OBSApp::GetRenderModule() const
  134. {
  135. const char *renderer = config_get_string(globalConfig, "Video",
  136. "Renderer");
  137. if (astrcmpi(renderer, "Direct3D 11") == 0)
  138. return "libobs-d3d11";
  139. else
  140. return "libobs-opengl";
  141. }
  142. void OBSApp::OBSInit()
  143. {
  144. mainWindow->OBSInit();
  145. }
  146. #ifdef __APPLE__
  147. #define INPUT_AUDIO_SOURCE "coreaudio_input_capture"
  148. #define OUTPUT_AUDIO_SOURCE "coreaudio_output_capture"
  149. #elif _WIN32
  150. #define INPUT_AUDIO_SOURCE "wasapi_input_capture"
  151. #define OUTPUT_AUDIO_SOURCE "wasapi_output_capture"
  152. #else
  153. #define INPUT_AUDIO_SOURCE "pulse_input_capture"
  154. #define OUTPUT_AUDIO_SOURCE "pulse_output_capture"
  155. #endif
  156. const char *OBSApp::InputAudioSource() const
  157. {
  158. return INPUT_AUDIO_SOURCE;
  159. }
  160. const char *OBSApp::OutputAudioSource() const
  161. {
  162. return OUTPUT_AUDIO_SOURCE;
  163. }
  164. struct NoFocusFrameStyle : QProxyStyle
  165. {
  166. void drawControl(ControlElement element, const QStyleOption *option,
  167. QPainter *painter, const QWidget *widget=nullptr)
  168. const override
  169. {
  170. if (element == CE_FocusFrame)
  171. return;
  172. QProxyStyle::drawControl(element, option, painter, widget);
  173. }
  174. };
  175. int main(int argc, char *argv[])
  176. {
  177. #ifndef WIN32
  178. signal(SIGPIPE, SIG_IGN);
  179. #endif
  180. int ret = -1;
  181. QCoreApplication::addLibraryPath(".");
  182. #ifdef _WIN32
  183. char *logPath = os_get_config_path("obs-studio/log.txt");
  184. fstream logFile;
  185. logFile.open(logPath, ios_base::in | ios_base::out | ios_base::trunc,
  186. _SH_DENYNO);
  187. bfree(logPath);
  188. if (logFile.is_open())
  189. base_set_log_handler(do_log, &logFile);
  190. #endif
  191. try {
  192. OBSApp program(argc, argv);
  193. program.setStyle(new NoFocusFrameStyle);
  194. program.OBSInit();
  195. ret = program.exec();
  196. } catch (const char *error) {
  197. blog(LOG_ERROR, "%s", error);
  198. }
  199. blog(LOG_INFO, "Number of memory leaks: %ld", bnum_allocs());
  200. base_set_log_handler(nullptr, nullptr);
  201. return ret;
  202. }