1
0

OBSBasic_Projectors.cpp 7.6 KB

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