OBSBasic_VolControl.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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 <widgets/VolControl.hpp>
  18. using namespace std;
  19. void OBSBasic::UpdateVolumeControlsDecayRate()
  20. {
  21. double meterDecayRate = config_get_double(activeConfiguration, "Audio", "MeterDecayRate");
  22. for (size_t i = 0; i < volumes.size(); i++) {
  23. volumes[i]->SetMeterDecayRate(meterDecayRate);
  24. }
  25. }
  26. void OBSBasic::UpdateVolumeControlsPeakMeterType()
  27. {
  28. uint32_t peakMeterTypeIdx = config_get_uint(activeConfiguration, "Audio", "PeakMeterType");
  29. enum obs_peak_meter_type peakMeterType;
  30. switch (peakMeterTypeIdx) {
  31. case 0:
  32. peakMeterType = SAMPLE_PEAK_METER;
  33. break;
  34. case 1:
  35. peakMeterType = TRUE_PEAK_METER;
  36. break;
  37. default:
  38. peakMeterType = SAMPLE_PEAK_METER;
  39. break;
  40. }
  41. for (size_t i = 0; i < volumes.size(); i++) {
  42. volumes[i]->setPeakMeterType(peakMeterType);
  43. }
  44. }
  45. void OBSBasic::ClearVolumeControls()
  46. {
  47. for (VolControl *vol : volumes)
  48. delete vol;
  49. volumes.clear();
  50. }
  51. void OBSBasic::RefreshVolumeColors()
  52. {
  53. for (VolControl *vol : volumes) {
  54. vol->refreshColors();
  55. }
  56. }
  57. void OBSBasic::HideAudioControl()
  58. {
  59. QAction *action = reinterpret_cast<QAction *>(sender());
  60. VolControl *vol = action->property("volControl").value<VolControl *>();
  61. obs_source_t *source = vol->GetSource();
  62. if (!SourceMixerHidden(source)) {
  63. SetSourceMixerHidden(source, true);
  64. DeactivateAudioSource(source);
  65. }
  66. }
  67. void OBSBasic::UnhideAllAudioControls()
  68. {
  69. auto UnhideAudioMixer = [this](obs_source_t *source) /* -- */
  70. {
  71. if (!obs_source_active(source))
  72. return true;
  73. if (!SourceMixerHidden(source))
  74. return true;
  75. SetSourceMixerHidden(source, false);
  76. ActivateAudioSource(source);
  77. return true;
  78. };
  79. using UnhideAudioMixer_t = decltype(UnhideAudioMixer);
  80. auto PreEnum = [](void *data, obs_source_t *source) -> bool /* -- */
  81. {
  82. return (*static_cast<UnhideAudioMixer_t *>(data))(source);
  83. };
  84. obs_enum_sources(PreEnum, &UnhideAudioMixer);
  85. }
  86. void OBSBasic::ToggleHideMixer()
  87. {
  88. OBSSceneItem item = GetCurrentSceneItem();
  89. OBSSource source = obs_sceneitem_get_source(item);
  90. if (!SourceMixerHidden(source)) {
  91. SetSourceMixerHidden(source, true);
  92. DeactivateAudioSource(source);
  93. } else {
  94. SetSourceMixerHidden(source, false);
  95. ActivateAudioSource(source);
  96. }
  97. }
  98. void OBSBasic::LockVolumeControl(bool lock)
  99. {
  100. QAction *action = reinterpret_cast<QAction *>(sender());
  101. VolControl *vol = action->property("volControl").value<VolControl *>();
  102. obs_source_t *source = vol->GetSource();
  103. OBSDataAutoRelease priv_settings = obs_source_get_private_settings(source);
  104. obs_data_set_bool(priv_settings, "volume_locked", lock);
  105. vol->EnableSlider(!lock);
  106. }
  107. void OBSBasic::VolControlContextMenu()
  108. {
  109. VolControl *vol = reinterpret_cast<VolControl *>(sender());
  110. /* ------------------- */
  111. QAction lockAction(QTStr("LockVolume"), this);
  112. lockAction.setCheckable(true);
  113. lockAction.setChecked(SourceVolumeLocked(vol->GetSource()));
  114. QAction hideAction(QTStr("Hide"), this);
  115. QAction unhideAllAction(QTStr("UnhideAll"), this);
  116. QAction mixerRenameAction(QTStr("Rename"), this);
  117. QAction copyFiltersAction(QTStr("Copy.Filters"), this);
  118. QAction pasteFiltersAction(QTStr("Paste.Filters"), this);
  119. QAction filtersAction(QTStr("Filters"), this);
  120. QAction propertiesAction(QTStr("Properties"), this);
  121. QAction advPropAction(QTStr("Basic.MainMenu.Edit.AdvAudio"), this);
  122. QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
  123. toggleControlLayoutAction.setCheckable(true);
  124. toggleControlLayoutAction.setChecked(
  125. config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
  126. /* ------------------- */
  127. connect(&hideAction, &QAction::triggered, this, &OBSBasic::HideAudioControl, Qt::DirectConnection);
  128. connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
  129. connect(&lockAction, &QAction::toggled, this, &OBSBasic::LockVolumeControl, Qt::DirectConnection);
  130. connect(&mixerRenameAction, &QAction::triggered, this, &OBSBasic::MixerRenameSource, Qt::DirectConnection);
  131. connect(&copyFiltersAction, &QAction::triggered, this, &OBSBasic::AudioMixerCopyFilters, Qt::DirectConnection);
  132. connect(&pasteFiltersAction, &QAction::triggered, this, &OBSBasic::AudioMixerPasteFilters,
  133. Qt::DirectConnection);
  134. connect(&filtersAction, &QAction::triggered, this, &OBSBasic::GetAudioSourceFilters, Qt::DirectConnection);
  135. connect(&propertiesAction, &QAction::triggered, this, &OBSBasic::GetAudioSourceProperties,
  136. Qt::DirectConnection);
  137. connect(&advPropAction, &QAction::triggered, this, &OBSBasic::on_actionAdvAudioProperties_triggered,
  138. Qt::DirectConnection);
  139. /* ------------------- */
  140. connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
  141. Qt::DirectConnection);
  142. /* ------------------- */
  143. hideAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  144. lockAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  145. mixerRenameAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  146. copyFiltersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  147. pasteFiltersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  148. filtersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  149. propertiesAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
  150. /* ------------------- */
  151. copyFiltersAction.setEnabled(obs_source_filter_count(vol->GetSource()) > 0);
  152. pasteFiltersAction.setEnabled(!obs_weak_source_expired(copyFiltersSource));
  153. QMenu popup;
  154. vol->SetContextMenu(&popup);
  155. popup.addAction(&lockAction);
  156. popup.addSeparator();
  157. popup.addAction(&unhideAllAction);
  158. popup.addAction(&hideAction);
  159. popup.addAction(&mixerRenameAction);
  160. popup.addSeparator();
  161. popup.addAction(&copyFiltersAction);
  162. popup.addAction(&pasteFiltersAction);
  163. popup.addSeparator();
  164. popup.addAction(&toggleControlLayoutAction);
  165. popup.addSeparator();
  166. popup.addAction(&filtersAction);
  167. popup.addAction(&propertiesAction);
  168. popup.addAction(&advPropAction);
  169. // toggleControlLayoutAction deletes and re-creates the volume controls
  170. // meaning that "vol" would be pointing to freed memory.
  171. if (popup.exec(QCursor::pos()) != &toggleControlLayoutAction)
  172. vol->SetContextMenu(nullptr);
  173. }
  174. void OBSBasic::on_hMixerScrollArea_customContextMenuRequested()
  175. {
  176. StackedMixerAreaContextMenuRequested();
  177. }
  178. void OBSBasic::on_vMixerScrollArea_customContextMenuRequested()
  179. {
  180. StackedMixerAreaContextMenuRequested();
  181. }
  182. void OBSBasic::StackedMixerAreaContextMenuRequested()
  183. {
  184. QAction unhideAllAction(QTStr("UnhideAll"), this);
  185. QAction advPropAction(QTStr("Basic.MainMenu.Edit.AdvAudio"), this);
  186. QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
  187. toggleControlLayoutAction.setCheckable(true);
  188. toggleControlLayoutAction.setChecked(
  189. config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
  190. /* ------------------- */
  191. connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
  192. connect(&advPropAction, &QAction::triggered, this, &OBSBasic::on_actionAdvAudioProperties_triggered,
  193. Qt::DirectConnection);
  194. /* ------------------- */
  195. connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
  196. Qt::DirectConnection);
  197. /* ------------------- */
  198. QMenu popup;
  199. popup.addAction(&unhideAllAction);
  200. popup.addSeparator();
  201. popup.addAction(&toggleControlLayoutAction);
  202. popup.addSeparator();
  203. popup.addAction(&advPropAction);
  204. popup.exec(QCursor::pos());
  205. }
  206. void OBSBasic::ToggleMixerLayout(bool vertical)
  207. {
  208. if (vertical) {
  209. ui->stackedMixerArea->setMinimumSize(180, 220);
  210. ui->stackedMixerArea->setCurrentIndex(1);
  211. } else {
  212. ui->stackedMixerArea->setMinimumSize(220, 0);
  213. ui->stackedMixerArea->setCurrentIndex(0);
  214. }
  215. }
  216. void OBSBasic::ToggleVolControlLayout()
  217. {
  218. bool vertical = !config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl");
  219. config_set_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl", vertical);
  220. ToggleMixerLayout(vertical);
  221. // We need to store it so we can delete current and then add
  222. // at the right order
  223. vector<OBSSource> sources;
  224. for (size_t i = 0; i != volumes.size(); i++)
  225. sources.emplace_back(volumes[i]->GetSource());
  226. ClearVolumeControls();
  227. for (const auto &source : sources)
  228. ActivateAudioSource(source);
  229. }
  230. void OBSBasic::on_actionMixerToolbarAdvAudio_triggered()
  231. {
  232. on_actionAdvAudioProperties_triggered();
  233. }
  234. void OBSBasic::on_actionMixerToolbarMenu_triggered()
  235. {
  236. QAction unhideAllAction(QTStr("UnhideAll"), this);
  237. connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
  238. QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
  239. toggleControlLayoutAction.setCheckable(true);
  240. toggleControlLayoutAction.setChecked(
  241. config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
  242. connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
  243. Qt::DirectConnection);
  244. QMenu popup;
  245. popup.addAction(&unhideAllAction);
  246. popup.addSeparator();
  247. popup.addAction(&toggleControlLayoutAction);
  248. popup.exec(QCursor::pos());
  249. }