OBSBasic_Projectors.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. Zachary Lund <[email protected]>
  4. Philippe Groarke <[email protected]>
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ******************************************************************************/
  16. #include "OBSBasic.hpp"
  17. #include "OBSProjector.hpp"
  18. obs_data_array_t *OBSBasic::SaveProjectors()
  19. {
  20. obs_data_array_t *savedProjectors = obs_data_array_create();
  21. auto saveProjector = [savedProjectors](OBSProjector *projector) {
  22. if (!projector)
  23. return;
  24. OBSDataAutoRelease data = obs_data_create();
  25. ProjectorType type = projector->GetProjectorType();
  26. switch (type) {
  27. case ProjectorType::Scene:
  28. case ProjectorType::Source: {
  29. OBSSource source = projector->GetSource();
  30. const char *name = obs_source_get_name(source);
  31. obs_data_set_string(data, "name", name);
  32. break;
  33. }
  34. default:
  35. break;
  36. }
  37. obs_data_set_int(data, "monitor", projector->GetMonitor());
  38. obs_data_set_int(data, "type", static_cast<int>(type));
  39. obs_data_set_string(data, "geometry", projector->saveGeometry().toBase64().constData());
  40. if (projector->IsAlwaysOnTopOverridden())
  41. obs_data_set_bool(data, "alwaysOnTop", projector->IsAlwaysOnTop());
  42. obs_data_set_bool(data, "alwaysOnTopOverridden", projector->IsAlwaysOnTopOverridden());
  43. obs_data_array_push_back(savedProjectors, data);
  44. };
  45. for (size_t i = 0; i < projectors.size(); i++)
  46. saveProjector(static_cast<OBSProjector *>(projectors[i]));
  47. return savedProjectors;
  48. }
  49. void OBSBasic::LoadSavedProjectors(obs_data_array_t *array)
  50. {
  51. size_t num = obs_data_array_count(array);
  52. for (size_t i = 0; i < num; i++) {
  53. OBSDataAutoRelease data = obs_data_array_item(array, i);
  54. SavedProjectorInfo info = {};
  55. info.monitor = obs_data_get_int(data, "monitor");
  56. info.type = static_cast<ProjectorType>(obs_data_get_int(data, "type"));
  57. info.geometry = std::string(obs_data_get_string(data, "geometry"));
  58. info.name = std::string(obs_data_get_string(data, "name"));
  59. info.alwaysOnTop = obs_data_get_bool(data, "alwaysOnTop");
  60. info.alwaysOnTopOverridden = obs_data_get_bool(data, "alwaysOnTopOverridden");
  61. OpenSavedProjector(&info);
  62. }
  63. }
  64. void OBSBasic::UpdateMultiviewProjectorMenu()
  65. {
  66. ui->multiviewProjectorMenu->clear();
  67. AddProjectorMenuMonitors(ui->multiviewProjectorMenu, this, &OBSBasic::OpenMultiviewProjector);
  68. }
  69. void OBSBasic::ClearProjectors()
  70. {
  71. for (size_t i = 0; i < projectors.size(); i++) {
  72. if (projectors[i])
  73. delete projectors[i];
  74. }
  75. projectors.clear();
  76. }
  77. QList<QString> OBSBasic::GetProjectorMenuMonitorsFormatted()
  78. {
  79. QList<QString> projectorsFormatted;
  80. QList<QScreen *> screens = QGuiApplication::screens();
  81. for (int i = 0; i < screens.size(); i++) {
  82. QScreen *screen = screens[i];
  83. QRect screenGeometry = screen->geometry();
  84. qreal ratio = screen->devicePixelRatio();
  85. QString name = "";
  86. #if defined(__APPLE__) || defined(_WIN32)
  87. name = screen->name();
  88. #else
  89. name = screen->model().simplified();
  90. if (name.length() > 1 && name.endsWith("-"))
  91. name.chop(1);
  92. #endif
  93. name = name.simplified();
  94. if (name.length() == 0) {
  95. name = QString("%1 %2").arg(QTStr("Display")).arg(QString::number(i + 1));
  96. }
  97. QString str = QString("%1: %2x%3 @ %4,%5")
  98. .arg(name, QString::number(screenGeometry.width() * ratio),
  99. QString::number(screenGeometry.height() * ratio),
  100. QString::number(screenGeometry.x()), QString::number(screenGeometry.y()));
  101. projectorsFormatted.push_back(str);
  102. }
  103. return projectorsFormatted;
  104. }
  105. void OBSBasic::DeleteProjector(OBSProjector *projector)
  106. {
  107. for (size_t i = 0; i < projectors.size(); i++) {
  108. if (projectors[i] == projector) {
  109. projectors[i]->deleteLater();
  110. projectors.erase(projectors.begin() + i);
  111. break;
  112. }
  113. }
  114. }
  115. OBSProjector *OBSBasic::OpenProjector(obs_source_t *source, int monitor, ProjectorType type)
  116. {
  117. /* seriously? 10 monitors? */
  118. if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
  119. return nullptr;
  120. bool closeProjectors = config_get_bool(App()->GetUserConfig(), "BasicWindow", "CloseExistingProjectors");
  121. if (closeProjectors && monitor > -1) {
  122. for (size_t i = projectors.size(); i > 0; i--) {
  123. size_t idx = i - 1;
  124. if (projectors[idx]->GetMonitor() == monitor)
  125. DeleteProjector(projectors[idx]);
  126. }
  127. }
  128. OBSProjector *projector = new OBSProjector(nullptr, source, monitor, type);
  129. projectors.emplace_back(projector);
  130. return projector;
  131. }
  132. void OBSBasic::OpenPreviewProjector()
  133. {
  134. int monitor = sender()->property("monitor").toInt();
  135. OpenProjector(nullptr, monitor, ProjectorType::Preview);
  136. }
  137. void OBSBasic::OpenSourceProjector()
  138. {
  139. int monitor = sender()->property("monitor").toInt();
  140. OBSSceneItem item = GetCurrentSceneItem();
  141. if (!item)
  142. return;
  143. OpenProjector(obs_sceneitem_get_source(item), monitor, ProjectorType::Source);
  144. }
  145. void OBSBasic::OpenMultiviewProjector()
  146. {
  147. int monitor = sender()->property("monitor").toInt();
  148. OpenProjector(nullptr, monitor, ProjectorType::Multiview);
  149. }
  150. void OBSBasic::OpenSceneProjector()
  151. {
  152. int monitor = sender()->property("monitor").toInt();
  153. OBSScene scene = GetCurrentScene();
  154. if (!scene)
  155. return;
  156. OpenProjector(obs_scene_get_source(scene), monitor, ProjectorType::Scene);
  157. }
  158. void OBSBasic::OpenPreviewWindow()
  159. {
  160. OpenProjector(nullptr, -1, ProjectorType::Preview);
  161. }
  162. void OBSBasic::OpenSourceWindow()
  163. {
  164. OBSSceneItem item = GetCurrentSceneItem();
  165. if (!item)
  166. return;
  167. OBSSource source = obs_sceneitem_get_source(item);
  168. OpenProjector(obs_sceneitem_get_source(item), -1, ProjectorType::Source);
  169. }
  170. void OBSBasic::OpenSceneWindow()
  171. {
  172. OBSScene scene = GetCurrentScene();
  173. if (!scene)
  174. return;
  175. OBSSource source = obs_scene_get_source(scene);
  176. OpenProjector(obs_scene_get_source(scene), -1, ProjectorType::Scene);
  177. }
  178. void OBSBasic::OpenSavedProjector(SavedProjectorInfo *info)
  179. {
  180. if (info) {
  181. OBSProjector *projector = nullptr;
  182. switch (info->type) {
  183. case ProjectorType::Source:
  184. case ProjectorType::Scene: {
  185. OBSSourceAutoRelease source = obs_get_source_by_name(info->name.c_str());
  186. if (!source)
  187. return;
  188. projector = OpenProjector(source, info->monitor, info->type);
  189. break;
  190. }
  191. default: {
  192. projector = OpenProjector(nullptr, info->monitor, info->type);
  193. break;
  194. }
  195. }
  196. if (projector && !info->geometry.empty() && info->monitor < 0) {
  197. QByteArray byteArray = QByteArray::fromBase64(QByteArray(info->geometry.c_str()));
  198. projector->restoreGeometry(byteArray);
  199. if (!WindowPositionValid(projector->normalGeometry())) {
  200. QRect rect = QGuiApplication::primaryScreen()->geometry();
  201. projector->setGeometry(
  202. QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), rect));
  203. }
  204. if (info->alwaysOnTopOverridden)
  205. projector->SetIsAlwaysOnTop(info->alwaysOnTop, true);
  206. }
  207. }
  208. }
  209. void OBSBasic::on_multiviewProjectorWindowed_triggered()
  210. {
  211. OpenProjector(nullptr, -1, ProjectorType::Multiview);
  212. }