OBSBasic_Projectors.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. for (SavedProjectorInfo *info : savedProjectorsArray) {
  52. delete info;
  53. }
  54. savedProjectorsArray.clear();
  55. size_t num = obs_data_array_count(array);
  56. for (size_t i = 0; i < num; i++) {
  57. OBSDataAutoRelease data = obs_data_array_item(array, i);
  58. SavedProjectorInfo *info = new SavedProjectorInfo();
  59. info->monitor = obs_data_get_int(data, "monitor");
  60. info->type = static_cast<ProjectorType>(obs_data_get_int(data, "type"));
  61. info->geometry = std::string(obs_data_get_string(data, "geometry"));
  62. info->name = std::string(obs_data_get_string(data, "name"));
  63. info->alwaysOnTop = obs_data_get_bool(data, "alwaysOnTop");
  64. info->alwaysOnTopOverridden = obs_data_get_bool(data, "alwaysOnTopOverridden");
  65. savedProjectorsArray.emplace_back(info);
  66. }
  67. }
  68. void OBSBasic::UpdateMultiviewProjectorMenu()
  69. {
  70. ui->multiviewProjectorMenu->clear();
  71. AddProjectorMenuMonitors(ui->multiviewProjectorMenu, this, &OBSBasic::OpenMultiviewProjector);
  72. }
  73. void OBSBasic::ClearProjectors()
  74. {
  75. for (size_t i = 0; i < projectors.size(); i++) {
  76. if (projectors[i])
  77. delete projectors[i];
  78. }
  79. projectors.clear();
  80. }
  81. QList<QString> OBSBasic::GetProjectorMenuMonitorsFormatted()
  82. {
  83. QList<QString> projectorsFormatted;
  84. QList<QScreen *> screens = QGuiApplication::screens();
  85. for (int i = 0; i < screens.size(); i++) {
  86. QScreen *screen = screens[i];
  87. QRect screenGeometry = screen->geometry();
  88. qreal ratio = screen->devicePixelRatio();
  89. QString name = "";
  90. #if defined(__APPLE__) || defined(_WIN32)
  91. name = screen->name();
  92. #else
  93. name = screen->model().simplified();
  94. if (name.length() > 1 && name.endsWith("-"))
  95. name.chop(1);
  96. #endif
  97. name = name.simplified();
  98. if (name.length() == 0) {
  99. name = QString("%1 %2").arg(QTStr("Display")).arg(QString::number(i + 1));
  100. }
  101. QString str = QString("%1: %2x%3 @ %4,%5")
  102. .arg(name, QString::number(screenGeometry.width() * ratio),
  103. QString::number(screenGeometry.height() * ratio),
  104. QString::number(screenGeometry.x()), QString::number(screenGeometry.y()));
  105. projectorsFormatted.push_back(str);
  106. }
  107. return projectorsFormatted;
  108. }
  109. void OBSBasic::DeleteProjector(OBSProjector *projector)
  110. {
  111. for (size_t i = 0; i < projectors.size(); i++) {
  112. if (projectors[i] == projector) {
  113. projectors[i]->deleteLater();
  114. projectors.erase(projectors.begin() + i);
  115. break;
  116. }
  117. }
  118. }
  119. OBSProjector *OBSBasic::OpenProjector(obs_source_t *source, int monitor, ProjectorType type)
  120. {
  121. /* seriously? 10 monitors? */
  122. if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
  123. return nullptr;
  124. bool closeProjectors = config_get_bool(App()->GetUserConfig(), "BasicWindow", "CloseExistingProjectors");
  125. if (closeProjectors && monitor > -1) {
  126. for (size_t i = projectors.size(); i > 0; i--) {
  127. size_t idx = i - 1;
  128. if (projectors[idx]->GetMonitor() == monitor)
  129. DeleteProjector(projectors[idx]);
  130. }
  131. }
  132. OBSProjector *projector = new OBSProjector(nullptr, source, monitor, type);
  133. projectors.emplace_back(projector);
  134. return projector;
  135. }
  136. void OBSBasic::OpenPreviewProjector()
  137. {
  138. int monitor = sender()->property("monitor").toInt();
  139. OpenProjector(nullptr, monitor, ProjectorType::Preview);
  140. }
  141. void OBSBasic::OpenSourceProjector()
  142. {
  143. int monitor = sender()->property("monitor").toInt();
  144. OBSSceneItem item = GetCurrentSceneItem();
  145. if (!item)
  146. return;
  147. OpenProjector(obs_sceneitem_get_source(item), monitor, ProjectorType::Source);
  148. }
  149. void OBSBasic::OpenMultiviewProjector()
  150. {
  151. int monitor = sender()->property("monitor").toInt();
  152. OpenProjector(nullptr, monitor, ProjectorType::Multiview);
  153. }
  154. void OBSBasic::OpenSceneProjector()
  155. {
  156. int monitor = sender()->property("monitor").toInt();
  157. OBSScene scene = GetCurrentScene();
  158. if (!scene)
  159. return;
  160. OpenProjector(obs_scene_get_source(scene), monitor, ProjectorType::Scene);
  161. }
  162. void OBSBasic::OpenPreviewWindow()
  163. {
  164. OpenProjector(nullptr, -1, ProjectorType::Preview);
  165. }
  166. void OBSBasic::OpenSourceWindow()
  167. {
  168. OBSSceneItem item = GetCurrentSceneItem();
  169. if (!item)
  170. return;
  171. OBSSource source = obs_sceneitem_get_source(item);
  172. OpenProjector(obs_sceneitem_get_source(item), -1, ProjectorType::Source);
  173. }
  174. void OBSBasic::OpenSceneWindow()
  175. {
  176. OBSScene scene = GetCurrentScene();
  177. if (!scene)
  178. return;
  179. OBSSource source = obs_scene_get_source(scene);
  180. OpenProjector(obs_scene_get_source(scene), -1, ProjectorType::Scene);
  181. }
  182. void OBSBasic::OpenSavedProjectors()
  183. {
  184. for (SavedProjectorInfo *info : savedProjectorsArray) {
  185. OpenSavedProjector(info);
  186. }
  187. }
  188. void OBSBasic::OpenSavedProjector(SavedProjectorInfo *info)
  189. {
  190. if (info) {
  191. OBSProjector *projector = nullptr;
  192. switch (info->type) {
  193. case ProjectorType::Source:
  194. case ProjectorType::Scene: {
  195. OBSSourceAutoRelease source = obs_get_source_by_name(info->name.c_str());
  196. if (!source)
  197. return;
  198. projector = OpenProjector(source, info->monitor, info->type);
  199. break;
  200. }
  201. default: {
  202. projector = OpenProjector(nullptr, info->monitor, info->type);
  203. break;
  204. }
  205. }
  206. if (projector && !info->geometry.empty() && info->monitor < 0) {
  207. QByteArray byteArray = QByteArray::fromBase64(QByteArray(info->geometry.c_str()));
  208. projector->restoreGeometry(byteArray);
  209. if (!WindowPositionValid(projector->normalGeometry())) {
  210. QRect rect = QGuiApplication::primaryScreen()->geometry();
  211. projector->setGeometry(
  212. QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), rect));
  213. }
  214. if (info->alwaysOnTopOverridden)
  215. projector->SetIsAlwaysOnTop(info->alwaysOnTop, true);
  216. }
  217. }
  218. }
  219. void OBSBasic::on_multiviewProjectorWindowed_triggered()
  220. {
  221. OpenProjector(nullptr, -1, ProjectorType::Multiview);
  222. }