obs-app.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. }
  132. const char *OBSApp::GetRenderModule() const
  133. {
  134. const char *renderer = config_get_string(globalConfig, "Video",
  135. "Renderer");
  136. if (astrcmpi(renderer, "Direct3D 11") == 0)
  137. return "libobs-d3d11";
  138. else
  139. return "libobs-opengl";
  140. }
  141. void OBSApp::OBSInit()
  142. {
  143. mainWindow = move(unique_ptr<OBSBasic>(new OBSBasic()));
  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. QString OBSTranslator::translate(const char *context, const char *sourceText,
  165. const char *disambiguation, int n) const
  166. {
  167. const char *out = nullptr;
  168. if (!text_lookup_getstr(App()->GetTextLookup(), sourceText, &out))
  169. return QString();
  170. UNUSED_PARAMETER(context);
  171. UNUSED_PARAMETER(disambiguation);
  172. UNUSED_PARAMETER(n);
  173. return QT_UTF8(out);
  174. }
  175. struct NoFocusFrameStyle : QProxyStyle
  176. {
  177. void drawControl(ControlElement element, const QStyleOption *option,
  178. QPainter *painter, const QWidget *widget=nullptr)
  179. const override
  180. {
  181. if (element == CE_FocusFrame)
  182. return;
  183. QProxyStyle::drawControl(element, option, painter, widget);
  184. }
  185. };
  186. int main(int argc, char *argv[])
  187. {
  188. #ifndef WIN32
  189. signal(SIGPIPE, SIG_IGN);
  190. #endif
  191. int ret = -1;
  192. QCoreApplication::addLibraryPath(".");
  193. #ifdef _WIN32
  194. char *logPath = os_get_config_path("obs-studio/log.txt");
  195. fstream logFile;
  196. logFile.open(logPath, ios_base::in | ios_base::out | ios_base::trunc,
  197. _SH_DENYNO);
  198. bfree(logPath);
  199. if (logFile.is_open())
  200. base_set_log_handler(do_log, &logFile);
  201. #endif
  202. try {
  203. OBSApp program(argc, argv);
  204. OBSTranslator test;
  205. program.installTranslator(&test);
  206. program.setStyle(new NoFocusFrameStyle);
  207. program.OBSInit();
  208. ret = program.exec();
  209. } catch (const char *error) {
  210. blog(LOG_ERROR, "%s", error);
  211. }
  212. blog(LOG_INFO, "Number of memory leaks: %ld", bnum_allocs());
  213. base_set_log_handler(nullptr, nullptr);
  214. return ret;
  215. }