context-bar-controls.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. #include "context-bar-controls.hpp"
  2. #include "qt-wrappers.hpp"
  3. #include "obs-app.hpp"
  4. #include <QStandardItemModel>
  5. #include <QColorDialog>
  6. #include <QFontDialog>
  7. #include "ui_browser-source-toolbar.h"
  8. #include "ui_device-select-toolbar.h"
  9. #include "ui_game-capture-toolbar.h"
  10. #include "ui_image-source-toolbar.h"
  11. #include "ui_color-source-toolbar.h"
  12. #include "ui_text-source-toolbar.h"
  13. #ifdef _WIN32
  14. #define get_os_module(win, mac, linux) obs_get_module(win)
  15. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, win)
  16. #elif __APPLE__
  17. #define get_os_module(win, mac, linux) obs_get_module(mac)
  18. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, mac)
  19. #else
  20. #define get_os_module(win, mac, linux) obs_get_module(linux)
  21. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, linux)
  22. #endif
  23. /* ========================================================================= */
  24. SourceToolbar::SourceToolbar(QWidget *parent, OBSSource source)
  25. : QWidget(parent),
  26. weakSource(OBSGetWeakRef(source)),
  27. props(obs_source_properties(source), obs_properties_destroy)
  28. {
  29. obs_data_t *settings = obs_source_get_settings(source);
  30. obs_properties_apply_settings(props.get(), settings);
  31. obs_data_release(settings);
  32. }
  33. /* ========================================================================= */
  34. BrowserToolbar::BrowserToolbar(QWidget *parent, OBSSource source)
  35. : SourceToolbar(parent, source), ui(new Ui_BrowserSourceToolbar)
  36. {
  37. ui->setupUi(this);
  38. }
  39. BrowserToolbar::~BrowserToolbar()
  40. {
  41. delete ui;
  42. }
  43. void BrowserToolbar::on_refresh_clicked()
  44. {
  45. OBSSource source = GetSource();
  46. if (!source) {
  47. return;
  48. }
  49. obs_property_t *p = obs_properties_get(props.get(), "refreshnocache");
  50. obs_property_button_clicked(p, source.Get());
  51. }
  52. /* ========================================================================= */
  53. ComboSelectToolbar::ComboSelectToolbar(QWidget *parent, OBSSource source)
  54. : SourceToolbar(parent, source), ui(new Ui_DeviceSelectToolbar)
  55. {
  56. ui->setupUi(this);
  57. }
  58. ComboSelectToolbar::~ComboSelectToolbar()
  59. {
  60. delete ui;
  61. }
  62. static int FillPropertyCombo(QComboBox *c, obs_property_t *p,
  63. const std::string &cur_id, bool is_int = false)
  64. {
  65. size_t count = obs_property_list_item_count(p);
  66. int cur_idx = -1;
  67. for (size_t i = 0; i < count; i++) {
  68. const char *name = obs_property_list_item_name(p, i);
  69. std::string id;
  70. if (is_int) {
  71. id = std::to_string(obs_property_list_item_int(p, i));
  72. } else {
  73. const char *val = obs_property_list_item_string(p, i);
  74. id = val ? val : "";
  75. }
  76. if (cur_id == id)
  77. cur_idx = (int)i;
  78. c->addItem(name, id.c_str());
  79. }
  80. return cur_idx;
  81. }
  82. static void SetComboItemDisabled(QComboBox *c, int idx)
  83. {
  84. QStandardItemModel *model =
  85. dynamic_cast<QStandardItemModel *>(c->model());
  86. QStandardItem *item = model->item(idx);
  87. item->setFlags(Qt::NoItemFlags);
  88. }
  89. void ComboSelectToolbar::Init()
  90. {
  91. OBSSource source = GetSource();
  92. if (!source) {
  93. return;
  94. }
  95. std::string cur_id;
  96. obs_data_t *settings = obs_source_get_settings(source);
  97. if (is_int) {
  98. cur_id = std::to_string(obs_data_get_int(settings, prop_name));
  99. } else {
  100. cur_id = obs_data_get_string(settings, prop_name);
  101. }
  102. obs_data_release(settings);
  103. ui->device->blockSignals(true);
  104. obs_property_t *p = obs_properties_get(props.get(), prop_name);
  105. int cur_idx = FillPropertyCombo(ui->device, p, cur_id, is_int);
  106. if (cur_idx == -1 || obs_property_list_item_disabled(p, cur_idx)) {
  107. if (cur_idx == -1) {
  108. ui->device->insertItem(
  109. 0,
  110. QTStr("Basic.Settings.Audio.UnknownAudioDevice"));
  111. cur_idx = 0;
  112. }
  113. SetComboItemDisabled(ui->device, cur_idx);
  114. } else {
  115. ui->device->setCurrentIndex(cur_idx);
  116. }
  117. ui->device->blockSignals(false);
  118. }
  119. void ComboSelectToolbar::UpdateActivateButtonName()
  120. {
  121. obs_property_t *p = obs_properties_get(props.get(), "activate");
  122. ui->activateButton->setText(obs_property_description(p));
  123. }
  124. void ComboSelectToolbar::on_device_currentIndexChanged(int idx)
  125. {
  126. OBSSource source = GetSource();
  127. if (idx == -1 || !source) {
  128. return;
  129. }
  130. QString id = ui->device->itemData(idx).toString();
  131. obs_data_t *settings = obs_data_create();
  132. if (is_int) {
  133. obs_data_set_int(settings, prop_name, id.toInt());
  134. } else {
  135. obs_data_set_string(settings, prop_name, QT_TO_UTF8(id));
  136. }
  137. obs_source_update(source, settings);
  138. obs_data_release(settings);
  139. }
  140. void ComboSelectToolbar::on_activateButton_clicked()
  141. {
  142. OBSSource source = GetSource();
  143. if (!source) {
  144. return;
  145. }
  146. obs_property_t *p = obs_properties_get(props.get(), "activate");
  147. if (!p) {
  148. return;
  149. }
  150. obs_property_button_clicked(p, source.Get());
  151. UpdateActivateButtonName();
  152. }
  153. AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source)
  154. : ComboSelectToolbar(parent, source)
  155. {
  156. }
  157. void AudioCaptureToolbar::Init()
  158. {
  159. delete ui->activateButton;
  160. ui->activateButton = nullptr;
  161. obs_module_t *mod =
  162. get_os_module("win-wasapi", "mac-capture", "linux-pulseaudio");
  163. const char *device_str =
  164. get_os_text(mod, "Device", "CoreAudio.Device", "Device");
  165. ui->deviceLabel->setText(device_str);
  166. prop_name = "device_id";
  167. ComboSelectToolbar::Init();
  168. }
  169. WindowCaptureToolbar::WindowCaptureToolbar(QWidget *parent, OBSSource source)
  170. : ComboSelectToolbar(parent, source)
  171. {
  172. }
  173. void WindowCaptureToolbar::Init()
  174. {
  175. delete ui->activateButton;
  176. ui->activateButton = nullptr;
  177. obs_module_t *mod =
  178. get_os_module("win-capture", "mac-capture", "linux-capture");
  179. const char *device_str = get_os_text(mod, "WindowCapture.Window",
  180. "WindowUtils.Window", "Window");
  181. ui->deviceLabel->setText(device_str);
  182. #if !defined(_WIN32) && !defined(__APPLE__) //linux
  183. prop_name = "capture_window";
  184. #else
  185. prop_name = "window";
  186. #endif
  187. #ifdef __APPLE__
  188. is_int = true;
  189. #endif
  190. ComboSelectToolbar::Init();
  191. }
  192. DisplayCaptureToolbar::DisplayCaptureToolbar(QWidget *parent, OBSSource source)
  193. : ComboSelectToolbar(parent, source)
  194. {
  195. }
  196. void DisplayCaptureToolbar::Init()
  197. {
  198. delete ui->activateButton;
  199. ui->activateButton = nullptr;
  200. obs_module_t *mod =
  201. get_os_module("win-capture", "mac-capture", "linux-capture");
  202. const char *device_str =
  203. get_os_text(mod, "Monitor", "DisplayCapture.Display", "Screen");
  204. ui->deviceLabel->setText(device_str);
  205. is_int = true;
  206. #ifdef _WIN32
  207. prop_name = "monitor";
  208. #elif __APPLE__
  209. prop_name = "display";
  210. #else
  211. prop_name = "screen";
  212. #endif
  213. ComboSelectToolbar::Init();
  214. }
  215. DeviceCaptureToolbar::DeviceCaptureToolbar(QWidget *parent, OBSSource source)
  216. : ComboSelectToolbar(parent, source)
  217. {
  218. }
  219. void DeviceCaptureToolbar::Init()
  220. {
  221. #ifndef _WIN32
  222. delete ui->activateButton;
  223. ui->activateButton = nullptr;
  224. #endif
  225. obs_module_t *mod =
  226. get_os_module("win-dshow", "mac-avcapture", "linux-v4l2");
  227. const char *device_str = obs_module_get_locale_text(mod, "Device");
  228. ui->deviceLabel->setText(device_str);
  229. #ifdef _WIN32
  230. prop_name = "video_device_id";
  231. #elif __APPLE__
  232. prop_name = "device";
  233. #else
  234. prop_name = "device_id";
  235. #endif
  236. #ifdef _WIN32
  237. UpdateActivateButtonName();
  238. #endif
  239. ComboSelectToolbar::Init();
  240. }
  241. /* ========================================================================= */
  242. GameCaptureToolbar::GameCaptureToolbar(QWidget *parent, OBSSource source)
  243. : SourceToolbar(parent, source), ui(new Ui_GameCaptureToolbar)
  244. {
  245. obs_property_t *p;
  246. int cur_idx;
  247. ui->setupUi(this);
  248. obs_module_t *mod = obs_get_module("win-capture");
  249. ui->modeLabel->setText(obs_module_get_locale_text(mod, "Mode"));
  250. ui->windowLabel->setText(
  251. obs_module_get_locale_text(mod, "WindowCapture.Window"));
  252. obs_data_t *settings = obs_source_get_settings(source);
  253. std::string cur_mode = obs_data_get_string(settings, "capture_mode");
  254. std::string cur_window = obs_data_get_string(settings, "window");
  255. obs_data_release(settings);
  256. ui->mode->blockSignals(true);
  257. p = obs_properties_get(props.get(), "capture_mode");
  258. cur_idx = FillPropertyCombo(ui->mode, p, cur_mode);
  259. ui->mode->setCurrentIndex(cur_idx);
  260. ui->mode->blockSignals(false);
  261. ui->window->blockSignals(true);
  262. p = obs_properties_get(props.get(), "window");
  263. cur_idx = FillPropertyCombo(ui->window, p, cur_window);
  264. ui->window->setCurrentIndex(cur_idx);
  265. ui->window->blockSignals(false);
  266. if (cur_idx != -1 && obs_property_list_item_disabled(p, cur_idx)) {
  267. SetComboItemDisabled(ui->window, cur_idx);
  268. }
  269. UpdateWindowVisibility();
  270. }
  271. GameCaptureToolbar::~GameCaptureToolbar()
  272. {
  273. delete ui;
  274. }
  275. void GameCaptureToolbar::UpdateWindowVisibility()
  276. {
  277. QString mode = ui->mode->currentData().toString();
  278. bool is_window = (mode == "window");
  279. ui->windowLabel->setVisible(is_window);
  280. ui->window->setVisible(is_window);
  281. ui->empty->setVisible(!is_window);
  282. }
  283. void GameCaptureToolbar::on_mode_currentIndexChanged(int idx)
  284. {
  285. OBSSource source = GetSource();
  286. if (idx == -1 || !source) {
  287. return;
  288. }
  289. QString id = ui->mode->itemData(idx).toString();
  290. obs_data_t *settings = obs_data_create();
  291. obs_data_set_string(settings, "capture_mode", QT_TO_UTF8(id));
  292. obs_source_update(source, settings);
  293. obs_data_release(settings);
  294. UpdateWindowVisibility();
  295. }
  296. void GameCaptureToolbar::on_window_currentIndexChanged(int idx)
  297. {
  298. OBSSource source = GetSource();
  299. if (idx == -1 || !source) {
  300. return;
  301. }
  302. QString id = ui->window->itemData(idx).toString();
  303. obs_data_t *settings = obs_data_create();
  304. obs_data_set_string(settings, "window", QT_TO_UTF8(id));
  305. obs_source_update(source, settings);
  306. obs_data_release(settings);
  307. }
  308. /* ========================================================================= */
  309. ImageSourceToolbar::ImageSourceToolbar(QWidget *parent, OBSSource source)
  310. : SourceToolbar(parent, source), ui(new Ui_ImageSourceToolbar)
  311. {
  312. ui->setupUi(this);
  313. obs_module_t *mod = obs_get_module("image-source");
  314. ui->pathLabel->setText(obs_module_get_locale_text(mod, "File"));
  315. obs_data_t *settings = obs_source_get_settings(source);
  316. std::string file = obs_data_get_string(settings, "file");
  317. obs_data_release(settings);
  318. ui->path->setText(file.c_str());
  319. }
  320. ImageSourceToolbar::~ImageSourceToolbar()
  321. {
  322. delete ui;
  323. }
  324. void ImageSourceToolbar::on_browse_clicked()
  325. {
  326. OBSSource source = GetSource();
  327. if (!source) {
  328. return;
  329. }
  330. obs_property_t *p = obs_properties_get(props.get(), "file");
  331. const char *desc = obs_property_description(p);
  332. const char *filter = obs_property_path_filter(p);
  333. const char *default_path = obs_property_path_default_path(p);
  334. QString path = OpenFile(this, desc, default_path, filter);
  335. if (path.isEmpty()) {
  336. return;
  337. }
  338. ui->path->setText(path);
  339. obs_data_t *settings = obs_data_create();
  340. obs_data_set_string(settings, "file", QT_TO_UTF8(path));
  341. obs_source_update(source, settings);
  342. obs_data_release(settings);
  343. }
  344. /* ========================================================================= */
  345. static inline QColor color_from_int(long long val)
  346. {
  347. return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
  348. (val >> 24) & 0xff);
  349. }
  350. static inline long long color_to_int(QColor color)
  351. {
  352. auto shift = [&](unsigned val, int shift) {
  353. return ((val & 0xff) << shift);
  354. };
  355. return shift(color.red(), 0) | shift(color.green(), 8) |
  356. shift(color.blue(), 16) | shift(color.alpha(), 24);
  357. }
  358. ColorSourceToolbar::ColorSourceToolbar(QWidget *parent, OBSSource source)
  359. : SourceToolbar(parent, source), ui(new Ui_ColorSourceToolbar)
  360. {
  361. ui->setupUi(this);
  362. obs_data_t *settings = obs_source_get_settings(source);
  363. unsigned int val = (unsigned int)obs_data_get_int(settings, "color");
  364. obs_data_release(settings);
  365. color = color_from_int(val);
  366. UpdateColor();
  367. }
  368. ColorSourceToolbar::~ColorSourceToolbar()
  369. {
  370. delete ui;
  371. }
  372. void ColorSourceToolbar::UpdateColor()
  373. {
  374. color.setAlpha(255);
  375. QPalette palette = QPalette(color);
  376. ui->color->setFrameStyle(QFrame::Sunken | QFrame::Panel);
  377. ui->color->setText(color.name(QColor::HexRgb));
  378. ui->color->setPalette(palette);
  379. ui->color->setStyleSheet(
  380. QString("background-color :%1; color: %2;")
  381. .arg(palette.color(QPalette::Window)
  382. .name(QColor::HexRgb))
  383. .arg(palette.color(QPalette::WindowText)
  384. .name(QColor::HexRgb)));
  385. ui->color->setAutoFillBackground(true);
  386. ui->color->setAlignment(Qt::AlignCenter);
  387. }
  388. void ColorSourceToolbar::on_choose_clicked()
  389. {
  390. OBSSource source = GetSource();
  391. if (!source) {
  392. return;
  393. }
  394. obs_property_t *p = obs_properties_get(props.get(), "color");
  395. const char *desc = obs_property_description(p);
  396. QColorDialog::ColorDialogOptions options;
  397. #ifndef _WIN32
  398. options |= QColorDialog::DontUseNativeDialog;
  399. #endif
  400. color = QColorDialog::getColor(color, this, desc, options);
  401. UpdateColor();
  402. obs_data_t *settings = obs_data_create();
  403. obs_data_set_int(settings, "color", color_to_int(color));
  404. obs_source_update(source, settings);
  405. obs_data_release(settings);
  406. }
  407. /* ========================================================================= */
  408. extern void MakeQFont(obs_data_t *font_obj, QFont &font, bool limit = false);
  409. TextSourceToolbar::TextSourceToolbar(QWidget *parent, OBSSource source)
  410. : SourceToolbar(parent, source), ui(new Ui_TextSourceToolbar)
  411. {
  412. ui->setupUi(this);
  413. obs_data_t *settings = obs_source_get_settings(source);
  414. const char *id = obs_source_get_unversioned_id(source);
  415. bool ft2 = strcmp(id, "text_ft2_source") == 0;
  416. bool read_from_file = obs_data_get_bool(
  417. settings, ft2 ? "from_file" : "read_from_file");
  418. obs_data_t *font_obj = obs_data_get_obj(settings, "font");
  419. MakeQFont(font_obj, font);
  420. obs_data_release(font_obj);
  421. unsigned int val = (unsigned int)obs_data_get_int(settings, "color");
  422. color = color_from_int(val);
  423. const char *text = obs_data_get_string(settings, "text");
  424. bool single_line = !read_from_file &&
  425. (!text || (strchr(text, '\n') == nullptr));
  426. ui->emptySpace->setVisible(!single_line);
  427. ui->text->setVisible(single_line);
  428. if (single_line)
  429. ui->text->setText(text);
  430. obs_data_release(settings);
  431. }
  432. TextSourceToolbar::~TextSourceToolbar()
  433. {
  434. delete ui;
  435. }
  436. void TextSourceToolbar::on_selectFont_clicked()
  437. {
  438. OBSSource source = GetSource();
  439. if (!source) {
  440. return;
  441. }
  442. QFontDialog::FontDialogOptions options;
  443. uint32_t flags;
  444. bool success;
  445. #ifndef _WIN32
  446. options = QFontDialog::DontUseNativeDialog;
  447. #endif
  448. font = QFontDialog::getFont(&success, font, this, "Pick a Font",
  449. options);
  450. if (!success) {
  451. return;
  452. }
  453. obs_data_t *font_obj = obs_data_create();
  454. obs_data_set_string(font_obj, "face", QT_TO_UTF8(font.family()));
  455. obs_data_set_string(font_obj, "style", QT_TO_UTF8(font.styleName()));
  456. obs_data_set_int(font_obj, "size", font.pointSize());
  457. flags = font.bold() ? OBS_FONT_BOLD : 0;
  458. flags |= font.italic() ? OBS_FONT_ITALIC : 0;
  459. flags |= font.underline() ? OBS_FONT_UNDERLINE : 0;
  460. flags |= font.strikeOut() ? OBS_FONT_STRIKEOUT : 0;
  461. obs_data_set_int(font_obj, "flags", flags);
  462. obs_data_t *settings = obs_data_create();
  463. obs_data_set_obj(settings, "font", font_obj);
  464. obs_data_release(font_obj);
  465. obs_source_update(source, settings);
  466. obs_data_release(settings);
  467. }
  468. void TextSourceToolbar::on_selectColor_clicked()
  469. {
  470. OBSSource source = GetSource();
  471. if (!source) {
  472. return;
  473. }
  474. obs_property_t *p = obs_properties_get(props.get(), "color");
  475. const char *desc = obs_property_description(p);
  476. QColorDialog::ColorDialogOptions options;
  477. #ifndef _WIN32
  478. options |= QColorDialog::DontUseNativeDialog;
  479. #endif
  480. QColor newColor = QColorDialog::getColor(color, this, desc, options);
  481. if (!newColor.isValid()) {
  482. return;
  483. }
  484. color = newColor;
  485. obs_data_t *settings = obs_data_create();
  486. obs_data_set_int(settings, "color", color_to_int(color));
  487. obs_source_update(source, settings);
  488. obs_data_release(settings);
  489. }
  490. void TextSourceToolbar::on_text_textChanged()
  491. {
  492. OBSSource source = GetSource();
  493. if (!source) {
  494. return;
  495. }
  496. obs_data_t *settings = obs_data_create();
  497. obs_data_set_string(settings, "text", QT_TO_UTF8(ui->text->text()));
  498. obs_source_update(source, settings);
  499. obs_data_release(settings);
  500. }