1 /******************************************************************************
2     Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 2 of the License, or
7     (at your option) any later version.
8 
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 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17 
18 #pragma once
19 
20 #include <QBuffer>
21 #include <QAction>
22 #include <QThread>
23 #include <QWidgetAction>
24 #include <QSystemTrayIcon>
25 #include <QStyledItemDelegate>
26 #include <obs.hpp>
27 #include <vector>
28 #include <memory>
29 #include "window-main.hpp"
30 #include "window-basic-interaction.hpp"
31 #include "window-basic-properties.hpp"
32 #include "window-basic-transform.hpp"
33 #include "window-basic-adv-audio.hpp"
34 #include "window-basic-filters.hpp"
35 #include "window-missing-files.hpp"
36 #include "window-projector.hpp"
37 #include "window-basic-about.hpp"
38 #include "auth-base.hpp"
39 #include "log-viewer.hpp"
40 #include "undo-stack-obs.hpp"
41 
42 #include <obs-frontend-internal.hpp>
43 
44 #include <util/platform.h>
45 #include <util/threading.h>
46 #include <util/util.hpp>
47 
48 #include <QPointer>
49 
50 class QMessageBox;
51 class QListWidgetItem;
52 class VolControl;
53 class OBSBasicStats;
54 
55 #include "ui_OBSBasic.h"
56 #include "ui_ColorSelect.h"
57 
58 #define DESKTOP_AUDIO_1 Str("DesktopAudioDevice1")
59 #define DESKTOP_AUDIO_2 Str("DesktopAudioDevice2")
60 #define AUX_AUDIO_1 Str("AuxAudioDevice1")
61 #define AUX_AUDIO_2 Str("AuxAudioDevice2")
62 #define AUX_AUDIO_3 Str("AuxAudioDevice3")
63 #define AUX_AUDIO_4 Str("AuxAudioDevice4")
64 
65 #define SIMPLE_ENCODER_X264 "x264"
66 #define SIMPLE_ENCODER_X264_LOWCPU "x264_lowcpu"
67 #define SIMPLE_ENCODER_QSV "qsv"
68 #define SIMPLE_ENCODER_NVENC "nvenc"
69 #define SIMPLE_ENCODER_AMD "amd"
70 
71 #define PREVIEW_EDGE_SIZE 10
72 
73 struct BasicOutputHandler;
74 
75 enum class QtDataRole {
76 	OBSRef = Qt::UserRole,
77 	OBSSignals,
78 };
79 
80 struct SavedProjectorInfo {
81 	ProjectorType type;
82 	int monitor;
83 	std::string geometry;
84 	std::string name;
85 	bool alwaysOnTop;
86 	bool alwaysOnTopOverridden;
87 };
88 
89 struct QuickTransition {
90 	QPushButton *button = nullptr;
91 	OBSSource source;
92 	obs_hotkey_id hotkey = OBS_INVALID_HOTKEY_ID;
93 	int duration = 0;
94 	int id = 0;
95 	bool fadeToBlack = false;
96 
QuickTransitionQuickTransition97 	inline QuickTransition() {}
QuickTransitionQuickTransition98 	inline QuickTransition(OBSSource source_, int duration_, int id_,
99 			       bool fadeToBlack_ = false)
100 		: source(source_),
101 		  duration(duration_),
102 		  id(id_),
103 		  fadeToBlack(fadeToBlack_),
104 		  renamedSignal(std::make_shared<OBSSignal>(
105 			  obs_source_get_signal_handler(source), "rename",
106 			  SourceRenamed, this))
107 	{
108 	}
109 
110 private:
111 	static void SourceRenamed(void *param, calldata_t *data);
112 	std::shared_ptr<OBSSignal> renamedSignal;
113 };
114 
115 class ColorSelect : public QWidget {
116 
117 public:
118 	explicit ColorSelect(QWidget *parent = 0);
119 
120 private:
121 	std::unique_ptr<Ui::ColorSelect> ui;
122 };
123 
124 class OBSBasic : public OBSMainWindow {
125 	Q_OBJECT
126 	Q_PROPERTY(QIcon imageIcon READ GetImageIcon WRITE SetImageIcon
127 			   DESIGNABLE true)
128 	Q_PROPERTY(QIcon colorIcon READ GetColorIcon WRITE SetColorIcon
129 			   DESIGNABLE true)
130 	Q_PROPERTY(QIcon slideshowIcon READ GetSlideshowIcon WRITE
131 			   SetSlideshowIcon DESIGNABLE true)
132 	Q_PROPERTY(QIcon audioInputIcon READ GetAudioInputIcon WRITE
133 			   SetAudioInputIcon DESIGNABLE true)
134 	Q_PROPERTY(QIcon audioOutputIcon READ GetAudioOutputIcon WRITE
135 			   SetAudioOutputIcon DESIGNABLE true)
136 	Q_PROPERTY(QIcon desktopCapIcon READ GetDesktopCapIcon WRITE
137 			   SetDesktopCapIcon DESIGNABLE true)
138 	Q_PROPERTY(QIcon windowCapIcon READ GetWindowCapIcon WRITE
139 			   SetWindowCapIcon DESIGNABLE true)
140 	Q_PROPERTY(QIcon gameCapIcon READ GetGameCapIcon WRITE SetGameCapIcon
141 			   DESIGNABLE true)
142 	Q_PROPERTY(QIcon cameraIcon READ GetCameraIcon WRITE SetCameraIcon
143 			   DESIGNABLE true)
144 	Q_PROPERTY(QIcon textIcon READ GetTextIcon WRITE SetTextIcon
145 			   DESIGNABLE true)
146 	Q_PROPERTY(QIcon mediaIcon READ GetMediaIcon WRITE SetMediaIcon
147 			   DESIGNABLE true)
148 	Q_PROPERTY(QIcon browserIcon READ GetBrowserIcon WRITE SetBrowserIcon
149 			   DESIGNABLE true)
150 	Q_PROPERTY(QIcon groupIcon READ GetGroupIcon WRITE SetGroupIcon
151 			   DESIGNABLE true)
152 	Q_PROPERTY(QIcon sceneIcon READ GetSceneIcon WRITE SetSceneIcon
153 			   DESIGNABLE true)
154 	Q_PROPERTY(QIcon defaultIcon READ GetDefaultIcon WRITE SetDefaultIcon
155 			   DESIGNABLE true)
156 
157 	friend class OBSAbout;
158 	friend class OBSBasicPreview;
159 	friend class OBSBasicStatusBar;
160 	friend class OBSBasicSourceSelect;
161 	friend class OBSBasicTransform;
162 	friend class OBSBasicSettings;
163 	friend class Auth;
164 	friend class AutoConfig;
165 	friend class AutoConfigStreamPage;
166 	friend class RecordButton;
167 	friend class ReplayBufferButton;
168 	friend class ExtraBrowsersModel;
169 	friend class ExtraBrowsersDelegate;
170 	friend class DeviceCaptureToolbar;
171 	friend class DeviceToolbarPropertiesThread;
172 	friend class OBSBasicSourceSelect;
173 	friend class OBSYoutubeActions;
174 	friend struct BasicOutputHandler;
175 	friend struct OBSStudioAPI;
176 
177 	enum class MoveDir { Up, Down, Left, Right };
178 
179 	enum DropType {
180 		DropType_RawText,
181 		DropType_Text,
182 		DropType_Image,
183 		DropType_Media,
184 		DropType_Html,
185 		DropType_Url,
186 	};
187 
188 private:
189 	obs_frontend_callbacks *api = nullptr;
190 
191 	std::shared_ptr<Auth> auth;
192 
193 	std::vector<VolControl *> volumes;
194 
195 	std::vector<OBSSignal> signalHandlers;
196 
197 	QList<QPointer<QDockWidget>> extraDocks;
198 
199 	bool loaded = false;
200 	long disableSaving = 1;
201 	bool projectChanged = false;
202 	bool previewEnabled = true;
203 
204 	std::list<const char *> copyStrings;
205 	const char *copyFiltersString = nullptr;
206 	bool copyVisible = true;
207 
208 	bool closing = false;
209 	QScopedPointer<QThread> devicePropertiesThread;
210 	QScopedPointer<QThread> whatsNewInitThread;
211 	QScopedPointer<QThread> updateCheckThread;
212 	QScopedPointer<QThread> introCheckThread;
213 	QScopedPointer<QThread> logUploadThread;
214 
215 	QPointer<OBSBasicInteraction> interaction;
216 	QPointer<OBSBasicProperties> properties;
217 	QPointer<OBSBasicTransform> transformWindow;
218 	QPointer<OBSBasicAdvAudio> advAudioWindow;
219 	QPointer<OBSBasicFilters> filters;
220 	QPointer<QDockWidget> statsDock;
221 	QPointer<OBSAbout> about;
222 	QPointer<OBSMissingFiles> missDialog;
223 	QPointer<OBSLogViewer> logView;
224 
225 	QPointer<QTimer> cpuUsageTimer;
226 	QPointer<QTimer> diskFullTimer;
227 
228 	QPointer<QTimer> nudge_timer;
229 	bool recent_nudge = false;
230 
231 	os_cpu_usage_info_t *cpuUsageInfo = nullptr;
232 
233 	OBSService service;
234 	std::unique_ptr<BasicOutputHandler> outputHandler;
235 	bool streamingStopping = false;
236 	bool recordingStopping = false;
237 	bool replayBufferStopping = false;
238 
239 	gs_vertbuffer_t *box = nullptr;
240 	gs_vertbuffer_t *boxLeft = nullptr;
241 	gs_vertbuffer_t *boxTop = nullptr;
242 	gs_vertbuffer_t *boxRight = nullptr;
243 	gs_vertbuffer_t *boxBottom = nullptr;
244 	gs_vertbuffer_t *circle = nullptr;
245 
246 	gs_vertbuffer_t *actionSafeMargin = nullptr;
247 	gs_vertbuffer_t *graphicsSafeMargin = nullptr;
248 	gs_vertbuffer_t *fourByThreeSafeMargin = nullptr;
249 	gs_vertbuffer_t *leftLine = nullptr;
250 	gs_vertbuffer_t *topLine = nullptr;
251 	gs_vertbuffer_t *rightLine = nullptr;
252 
253 	int previewX = 0, previewY = 0;
254 	int previewCX = 0, previewCY = 0;
255 	float previewScale = 0.0f;
256 
257 	ConfigFile basicConfig;
258 
259 	std::vector<SavedProjectorInfo *> savedProjectorsArray;
260 	std::vector<OBSProjector *> projectors;
261 
262 	QPointer<QWidget> stats;
263 	QPointer<QWidget> remux;
264 	QPointer<QWidget> extraBrowsers;
265 	QPointer<QWidget> importer;
266 
267 	QPointer<QMenu> startStreamMenu;
268 
269 	QPointer<QPushButton> transitionButton;
270 	QPointer<QPushButton> replayBufferButton;
271 	QPointer<QHBoxLayout> replayLayout;
272 	QScopedPointer<QPushButton> pause;
273 	QScopedPointer<QPushButton> replay;
274 
275 	QPointer<QPushButton> vcamButton;
276 	bool vcamEnabled = false;
277 
278 	QScopedPointer<QSystemTrayIcon> trayIcon;
279 	QPointer<QAction> sysTrayStream;
280 	QPointer<QAction> sysTrayRecord;
281 	QPointer<QAction> sysTrayReplayBuffer;
282 	QPointer<QAction> sysTrayVirtualCam;
283 	QPointer<QAction> showHide;
284 	QPointer<QAction> exit;
285 	QPointer<QMenu> trayMenu;
286 	QPointer<QMenu> previewProjector;
287 	QPointer<QMenu> studioProgramProjector;
288 	QPointer<QMenu> multiviewProjectorMenu;
289 	QPointer<QMenu> previewProjectorSource;
290 	QPointer<QMenu> previewProjectorMain;
291 	QPointer<QMenu> sceneProjectorMenu;
292 	QPointer<QMenu> sourceProjector;
293 	QPointer<QMenu> scaleFilteringMenu;
294 	QPointer<QMenu> colorMenu;
295 	QPointer<QWidgetAction> colorWidgetAction;
296 	QPointer<ColorSelect> colorSelect;
297 	QPointer<QMenu> deinterlaceMenu;
298 	QPointer<QMenu> perSceneTransitionMenu;
299 	QPointer<QObject> shortcutFilter;
300 	QPointer<QAction> renameScene;
301 	QPointer<QAction> renameSource;
302 
303 	QPointer<QWidget> programWidget;
304 	QPointer<QVBoxLayout> programLayout;
305 	QPointer<QLabel> programLabel;
306 
307 	QScopedPointer<QThread> patronJsonThread;
308 	std::string patronJson;
309 
310 	void UpdateMultiviewProjectorMenu();
311 
312 	void DrawBackdrop(float cx, float cy);
313 
314 	void SetupEncoders();
315 
316 	void CreateFirstRunSources();
317 	void CreateDefaultScene(bool firstStart);
318 
319 	void UpdateVolumeControlsDecayRate();
320 	void UpdateVolumeControlsPeakMeterType();
321 	void ClearVolumeControls();
322 
323 	void UploadLog(const char *subdir, const char *file, const bool crash);
324 
325 	void Save(const char *file);
326 	void LoadData(obs_data_t *data, const char *file);
327 	void Load(const char *file);
328 
329 	void InitHotkeys();
330 	void CreateHotkeys();
331 	void ClearHotkeys();
332 
333 	bool InitService();
334 
335 	bool InitBasicConfigDefaults();
336 	void InitBasicConfigDefaults2();
337 	bool InitBasicConfig();
338 
339 	void InitOBSCallbacks();
340 
341 	void InitPrimitives();
342 
343 	void OnFirstLoad();
344 
345 	OBSSceneItem GetSceneItem(QListWidgetItem *item);
346 	OBSSceneItem GetCurrentSceneItem();
347 
348 	bool QueryRemoveSource(obs_source_t *source);
349 
350 	void TimedCheckForUpdates();
351 	void CheckForUpdates(bool manualUpdate);
352 
353 	void GetFPSCommon(uint32_t &num, uint32_t &den) const;
354 	void GetFPSInteger(uint32_t &num, uint32_t &den) const;
355 	void GetFPSFraction(uint32_t &num, uint32_t &den) const;
356 	void GetFPSNanoseconds(uint32_t &num, uint32_t &den) const;
357 	void GetConfigFPS(uint32_t &num, uint32_t &den) const;
358 
359 	void UpdatePreviewScalingMenu();
360 
361 	void LoadSceneListOrder(obs_data_array_t *array);
362 	obs_data_array_t *SaveSceneListOrder();
363 	void ChangeSceneIndex(bool relative, int idx, int invalidIdx);
364 
365 	void TempFileOutput(const char *path, int vBitrate, int aBitrate);
366 	void TempStreamOutput(const char *url, const char *key, int vBitrate,
367 			      int aBitrate);
368 
369 	void CloseDialogs();
370 	void ClearSceneData();
371 	void ClearProjectors();
372 
373 	void Nudge(int dist, MoveDir dir);
374 
375 	OBSProjector *OpenProjector(obs_source_t *source, int monitor,
376 				    ProjectorType type);
377 
378 	void GetAudioSourceFilters();
379 	void GetAudioSourceProperties();
380 	void VolControlContextMenu();
381 	void ToggleVolControlLayout();
382 	void ToggleMixerLayout(bool vertical);
383 
384 	void RefreshSceneCollections();
385 	void ChangeSceneCollection();
386 	void LogScenes();
387 
388 	void ResetProfileData();
389 	bool AddProfile(bool create_new, const char *title, const char *text,
390 			const char *init_text = nullptr, bool rename = false);
391 	bool CreateProfile(const std::string &newName, bool create_new,
392 			   bool showWizardChecked, bool rename = false);
393 	void DeleteProfile(const char *profile_name, const char *profile_dir);
394 	void RefreshProfiles();
395 	void ChangeProfile();
396 	void CheckForSimpleModeX264Fallback();
397 
398 	void SaveProjectNow();
399 
400 	int GetTopSelectedSourceItem();
401 
402 	QModelIndexList GetAllSelectedSourceItems();
403 
404 	obs_hotkey_pair_id streamingHotkeys, recordingHotkeys, pauseHotkeys,
405 		replayBufHotkeys, vcamHotkeys, togglePreviewHotkeys,
406 		contextBarHotkeys;
407 	obs_hotkey_id forceStreamingStopHotkey;
408 
409 	void InitDefaultTransitions();
410 	void InitTransition(obs_source_t *transition);
411 	obs_source_t *FindTransition(const char *name);
412 	OBSSource GetCurrentTransition();
413 	obs_data_array_t *SaveTransitions();
414 	void LoadTransitions(obs_data_array_t *transitions,
415 			     obs_load_source_cb cb, void *private_data);
416 
417 	obs_source_t *fadeTransition;
418 	obs_source_t *cutTransition;
419 
420 	void CreateProgramDisplay();
421 	void CreateProgramOptions();
422 	int TransitionCount();
423 	int AddTransitionBeforeSeparator(const QString &name,
424 					 obs_source_t *source);
425 	void AddQuickTransitionId(int id);
426 	void AddQuickTransition();
427 	void AddQuickTransitionHotkey(QuickTransition *qt);
428 	void RemoveQuickTransitionHotkey(QuickTransition *qt);
429 	void LoadQuickTransitions(obs_data_array_t *array);
430 	obs_data_array_t *SaveQuickTransitions();
431 	void ClearQuickTransitionWidgets();
432 	void RefreshQuickTransitions();
433 	void DisableQuickTransitionWidgets();
434 	void EnableTransitionWidgets(bool enable);
435 	void CreateDefaultQuickTransitions();
436 
437 	QMenu *CreatePerSceneTransitionMenu();
438 	QMenu *CreateVisibilityTransitionMenu(bool visible);
439 
440 	QuickTransition *GetQuickTransition(int id);
441 	int GetQuickTransitionIdx(int id);
442 	QMenu *CreateTransitionMenu(QWidget *parent, QuickTransition *qt);
443 	void ClearQuickTransitions();
444 	void QuickTransitionClicked();
445 	void QuickTransitionChange();
446 	void QuickTransitionChangeDuration(int value);
447 	void QuickTransitionRemoveClicked();
448 
449 	void SetPreviewProgramMode(bool enabled);
450 	void ResizeProgram(uint32_t cx, uint32_t cy);
451 	void SetCurrentScene(obs_scene_t *scene, bool force = false);
452 	static void RenderProgram(void *data, uint32_t cx, uint32_t cy);
453 
454 	std::vector<QuickTransition> quickTransitions;
455 	QPointer<QWidget> programOptions;
456 	QPointer<OBSQTDisplay> program;
457 	OBSWeakSource lastScene;
458 	OBSWeakSource swapScene;
459 	OBSWeakSource programScene;
460 	bool editPropertiesMode = false;
461 	bool sceneDuplicationMode = true;
462 	bool swapScenesMode = true;
463 	volatile bool previewProgramMode = false;
464 	obs_hotkey_id togglePreviewProgramHotkey = 0;
465 	obs_hotkey_id transitionHotkey = 0;
466 	obs_hotkey_id statsHotkey = 0;
467 	obs_hotkey_id screenshotHotkey = 0;
468 	obs_hotkey_id sourceScreenshotHotkey = 0;
469 	int quickTransitionIdCounter = 1;
470 	bool overridingTransition = false;
471 
472 	int programX = 0, programY = 0;
473 	int programCX = 0, programCY = 0;
474 	float programScale = 0.0f;
475 
476 	int disableOutputsRef = 0;
477 
478 	inline void OnActivate();
479 	inline void OnDeactivate();
480 
481 	void AddDropSource(const char *file, DropType image);
482 	void AddDropURL(const char *url, QString &name, obs_data_t *settings,
483 			const obs_video_info &ovi);
484 	void ConfirmDropUrl(const QString &url);
485 	void dragEnterEvent(QDragEnterEvent *event) override;
486 	void dragLeaveEvent(QDragLeaveEvent *event) override;
487 	void dragMoveEvent(QDragMoveEvent *event) override;
488 	void dropEvent(QDropEvent *event) override;
489 
490 	void ReplayBufferClicked();
491 
492 	bool sysTrayMinimizeToTray();
493 
494 	void EnumDialogs();
495 
496 	QList<QDialog *> visDialogs;
497 	QList<QDialog *> modalDialogs;
498 	QList<QMessageBox *> visMsgBoxes;
499 
500 	QList<QPoint> visDlgPositions;
501 
502 	QByteArray startingDockLayout;
503 
504 	obs_data_array_t *SaveProjectors();
505 	void LoadSavedProjectors(obs_data_array_t *savedProjectors);
506 
507 	void ReceivedIntroJson(const QString &text);
508 	void ShowWhatsNew(const QString &url);
509 
510 #ifdef BROWSER_AVAILABLE
511 	QList<QSharedPointer<QDockWidget>> extraBrowserDocks;
512 	QList<QSharedPointer<QAction>> extraBrowserDockActions;
513 	QStringList extraBrowserDockTargets;
514 
515 	void ClearExtraBrowserDocks();
516 	void LoadExtraBrowserDocks();
517 	void SaveExtraBrowserDocks();
518 	void ManageExtraBrowserDocks();
519 	void AddExtraBrowserDock(const QString &title, const QString &url,
520 				 bool firstCreate);
521 #endif
522 
523 	QIcon imageIcon;
524 	QIcon colorIcon;
525 	QIcon slideshowIcon;
526 	QIcon audioInputIcon;
527 	QIcon audioOutputIcon;
528 	QIcon desktopCapIcon;
529 	QIcon windowCapIcon;
530 	QIcon gameCapIcon;
531 	QIcon cameraIcon;
532 	QIcon textIcon;
533 	QIcon mediaIcon;
534 	QIcon browserIcon;
535 	QIcon groupIcon;
536 	QIcon sceneIcon;
537 	QIcon defaultIcon;
538 
539 	QIcon GetImageIcon() const;
540 	QIcon GetColorIcon() const;
541 	QIcon GetSlideshowIcon() const;
542 	QIcon GetAudioInputIcon() const;
543 	QIcon GetAudioOutputIcon() const;
544 	QIcon GetDesktopCapIcon() const;
545 	QIcon GetWindowCapIcon() const;
546 	QIcon GetGameCapIcon() const;
547 	QIcon GetCameraIcon() const;
548 	QIcon GetTextIcon() const;
549 	QIcon GetMediaIcon() const;
550 	QIcon GetBrowserIcon() const;
551 	QIcon GetDefaultIcon() const;
552 
553 	QSlider *tBar;
554 	bool tBarActive = false;
555 
556 	OBSSource GetOverrideTransition(OBSSource source);
557 	int GetOverrideTransitionDuration(OBSSource source);
558 
559 	void UpdateProjectorHideCursor();
560 	void UpdateProjectorAlwaysOnTop(bool top);
561 	void ResetProjectors();
562 
563 	QPointer<QObject> screenshotData;
564 
565 	void MoveSceneItem(enum obs_order_movement movement,
566 			   const QString &action_name);
567 
568 	bool autoStartBroadcast = true;
569 	bool autoStopBroadcast = true;
570 	bool broadcastActive = false;
571 	bool broadcastReady = false;
572 	QPointer<QThread> youtubeStreamCheckThread;
573 #if YOUTUBE_ENABLED
574 	void YoutubeStreamCheck(const std::string &key);
575 	void ShowYouTubeAutoStartWarning();
576 	void YouTubeActionDialogOk(const QString &id, const QString &key,
577 				   bool autostart, bool autostop,
578 				   bool start_now);
579 #endif
580 	void BroadcastButtonClicked();
581 	void SetBroadcastFlowEnabled(bool enabled);
582 
583 	void UpdatePreviewSafeAreas();
584 	bool drawSafeAreas = false;
585 
586 public slots:
587 	void DeferSaveBegin();
588 	void DeferSaveEnd();
589 
590 	void DisplayStreamStartError();
591 
592 	void SetupBroadcast();
593 
594 	void StartStreaming();
595 	void StopStreaming();
596 	void ForceStopStreaming();
597 
598 	void StreamDelayStarting(int sec);
599 	void StreamDelayStopping(int sec);
600 
601 	void StreamingStart();
602 	void StreamStopping();
603 	void StreamingStop(int errorcode, QString last_error);
604 
605 	void StartRecording();
606 	void StopRecording();
607 
608 	void RecordingStart();
609 	void RecordStopping();
610 	void RecordingStop(int code, QString last_error);
611 
612 	void ShowReplayBufferPauseWarning();
613 	void StartReplayBuffer();
614 	void StopReplayBuffer();
615 
616 	void ReplayBufferStart();
617 	void ReplayBufferSave();
618 	void ReplayBufferSaved();
619 	void ReplayBufferStopping();
620 	void ReplayBufferStop(int code);
621 
622 	void StartVirtualCam();
623 	void StopVirtualCam();
624 
625 	void OnVirtualCamStart();
626 	void OnVirtualCamStop(int code);
627 
628 	void SaveProjectDeferred();
629 	void SaveProject();
630 
631 	void SetTransition(OBSSource transition);
632 	void OverrideTransition(OBSSource transition);
633 	void TransitionToScene(OBSScene scene, bool force = false);
634 	void TransitionToScene(OBSSource scene, bool force = false,
635 			       bool quickTransition = false,
636 			       int quickDuration = 0, bool black = false,
637 			       bool manual = false);
638 	void SetCurrentScene(OBSSource scene, bool force = false);
639 
640 	bool AddSceneCollection(bool create_new,
641 				const QString &name = QString());
642 
643 	bool NewProfile(const QString &name);
644 	bool DuplicateProfile(const QString &name);
645 	void DeleteProfile(const QString &profileName);
646 
647 	void UpdatePatronJson(const QString &text, const QString &error);
648 
649 	void ShowContextBar();
650 	void HideContextBar();
651 	void PauseRecording();
652 	void UnpauseRecording();
653 
654 private slots:
655 
656 	void on_actionMainUndo_triggered();
657 	void on_actionMainRedo_triggered();
658 
659 	void AddSceneItem(OBSSceneItem item);
660 	void AddScene(OBSSource source);
661 	void RemoveScene(OBSSource source);
662 	void RenameSources(OBSSource source, QString newName, QString prevName);
663 
664 	void ActivateAudioSource(OBSSource source);
665 	void DeactivateAudioSource(OBSSource source);
666 
667 	void DuplicateSelectedScene();
668 	void RemoveSelectedScene();
669 
670 	void ToggleAlwaysOnTop();
671 
672 	void ReorderSources(OBSScene scene);
673 	void RefreshSources(OBSScene scene);
674 
675 	void ProcessHotkey(obs_hotkey_id id, bool pressed);
676 
677 	void AddTransition(QString id);
678 	void RenameTransition();
679 	void TransitionClicked();
680 	void TransitionStopped();
681 	void TransitionFullyStopped();
682 	void TriggerQuickTransition(int id);
683 
684 	void SetDeinterlacingMode();
685 	void SetDeinterlacingOrder();
686 
687 	void SetScaleFilter();
688 
689 	void IconActivated(QSystemTrayIcon::ActivationReason reason);
690 	void SetShowing(bool showing);
691 
692 	void ToggleShowHide();
693 
694 	void HideAudioControl();
695 	void UnhideAllAudioControls();
696 	void ToggleHideMixer();
697 
698 	void MixerRenameSource();
699 
700 	void on_vMixerScrollArea_customContextMenuRequested();
701 	void on_hMixerScrollArea_customContextMenuRequested();
702 
703 	void on_actionCopySource_triggered();
704 	void on_actionPasteRef_triggered();
705 	void on_actionPasteDup_triggered();
706 
707 	void on_actionCopyFilters_triggered();
708 	void on_actionPasteFilters_triggered();
709 
710 	void ColorChange();
711 
712 	SourceTreeItem *GetItemWidgetFromSceneItem(obs_sceneitem_t *sceneItem);
713 
714 	void on_actionShowAbout_triggered();
715 
716 	void AudioMixerCopyFilters();
717 	void AudioMixerPasteFilters();
718 
719 	void EnablePreview();
720 	void DisablePreview();
721 
722 	void SceneCopyFilters();
723 	void ScenePasteFilters();
724 
725 	void CheckDiskSpaceRemaining();
726 	void OpenSavedProjector(SavedProjectorInfo *info);
727 
728 	void ScenesReordered();
729 
730 	void ResetStatsHotkey();
731 
732 	void SetImageIcon(const QIcon &icon);
733 	void SetColorIcon(const QIcon &icon);
734 	void SetSlideshowIcon(const QIcon &icon);
735 	void SetAudioInputIcon(const QIcon &icon);
736 	void SetAudioOutputIcon(const QIcon &icon);
737 	void SetDesktopCapIcon(const QIcon &icon);
738 	void SetWindowCapIcon(const QIcon &icon);
739 	void SetGameCapIcon(const QIcon &icon);
740 	void SetCameraIcon(const QIcon &icon);
741 	void SetTextIcon(const QIcon &icon);
742 	void SetMediaIcon(const QIcon &icon);
743 	void SetBrowserIcon(const QIcon &icon);
744 	void SetGroupIcon(const QIcon &icon);
745 	void SetSceneIcon(const QIcon &icon);
746 	void SetDefaultIcon(const QIcon &icon);
747 
748 	void TBarChanged(int value);
749 	void TBarReleased();
750 
751 	void LockVolumeControl(bool lock);
752 
753 private:
754 	/* OBS Callbacks */
755 	static void SceneReordered(void *data, calldata_t *params);
756 	static void SceneRefreshed(void *data, calldata_t *params);
757 	static void SceneItemAdded(void *data, calldata_t *params);
758 	static void SourceCreated(void *data, calldata_t *params);
759 	static void SourceRemoved(void *data, calldata_t *params);
760 	static void SourceActivated(void *data, calldata_t *params);
761 	static void SourceDeactivated(void *data, calldata_t *params);
762 	static void SourceAudioActivated(void *data, calldata_t *params);
763 	static void SourceAudioDeactivated(void *data, calldata_t *params);
764 	static void SourceRenamed(void *data, calldata_t *params);
765 	static void RenderMain(void *data, uint32_t cx, uint32_t cy);
766 
767 	void ResizePreview(uint32_t cx, uint32_t cy);
768 
769 	void AddSource(const char *id);
770 	QMenu *CreateAddSourcePopupMenu();
771 	void AddSourcePopupMenu(const QPoint &pos);
772 	void copyActionsDynamicProperties();
773 
774 	static void HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed);
775 
776 	void AutoRemux(QString input);
777 
778 	void UpdatePause(bool activate = true);
779 	void UpdateReplayBuffer(bool activate = true);
780 
781 	bool OutputPathValid();
782 	void OutputPathInvalidMessage();
783 
784 	bool LowDiskSpace();
785 	void DiskSpaceMessage();
786 
787 	OBSSource prevFTBSource = nullptr;
788 
789 public:
790 	undo_stack undo_s;
791 	OBSSource GetProgramSource();
792 	OBSScene GetCurrentScene();
793 
794 	void SysTrayNotify(const QString &text, QSystemTrayIcon::MessageIcon n);
795 
GetCurrentSceneSource()796 	inline OBSSource GetCurrentSceneSource()
797 	{
798 		OBSScene curScene = GetCurrentScene();
799 		return OBSSource(obs_scene_get_source(curScene));
800 	}
801 
802 	obs_service_t *GetService();
803 	void SetService(obs_service_t *service);
804 
805 	int GetTransitionDuration();
806 	int GetTbarPosition();
807 
IsPreviewProgramMode() const808 	inline bool IsPreviewProgramMode() const
809 	{
810 		return os_atomic_load_bool(&previewProgramMode);
811 	}
812 
VCamEnabled() const813 	inline bool VCamEnabled() const { return vcamEnabled; }
814 
815 	bool StreamingActive() const;
816 	bool Active() const;
817 
818 	void ResetUI();
819 	int ResetVideo();
820 	bool ResetAudio();
821 
822 	void AddVCamButton();
823 	void ResetOutputs();
824 
825 	void ResetAudioDevice(const char *sourceId, const char *deviceId,
826 			      const char *deviceDesc, int channel);
827 
828 	void NewProject();
829 	void LoadProject();
830 
GetDisplayRect(int & x,int & y,int & cx,int & cy)831 	inline void GetDisplayRect(int &x, int &y, int &cx, int &cy)
832 	{
833 		x = previewX;
834 		y = previewY;
835 		cx = previewCX;
836 		cy = previewCY;
837 	}
838 
SavingDisabled() const839 	inline bool SavingDisabled() const { return disableSaving; }
840 
GetCPUUsage() const841 	inline double GetCPUUsage() const
842 	{
843 		return os_cpu_usage_info_query(cpuUsageInfo);
844 	}
845 
846 	void SaveService();
847 	bool LoadService();
848 
GetAuth()849 	inline Auth *GetAuth() { return auth.get(); }
850 
EnableOutputs(bool enable)851 	inline void EnableOutputs(bool enable)
852 	{
853 		if (enable) {
854 			if (--disableOutputsRef < 0)
855 				disableOutputsRef = 0;
856 		} else {
857 			disableOutputsRef++;
858 		}
859 	}
860 
861 	QMenu *AddDeinterlacingMenu(QMenu *menu, obs_source_t *source);
862 	QMenu *AddScaleFilteringMenu(QMenu *menu, obs_sceneitem_t *item);
863 	QMenu *AddBackgroundColorMenu(QMenu *menu, QWidgetAction *widgetAction,
864 				      ColorSelect *select,
865 				      obs_sceneitem_t *item);
866 	void CreateSourcePopupMenu(int idx, bool preview);
867 
868 	void UpdateTitleBar();
869 
870 	void SystemTrayInit();
871 	void SystemTray(bool firstStarted);
872 
873 	void OpenSavedProjectors();
874 
875 	void CreateInteractionWindow(obs_source_t *source);
876 	void CreatePropertiesWindow(obs_source_t *source);
877 	void CreateFiltersWindow(obs_source_t *source);
878 
879 	QAction *AddDockWidget(QDockWidget *dock);
880 
881 	static OBSBasic *Get();
882 
883 	const char *GetCurrentOutputPath();
884 
885 	void DeleteProjector(OBSProjector *projector);
886 	void AddProjectorMenuMonitors(QMenu *parent, QObject *target,
887 				      const char *slot);
888 
889 	QIcon GetSourceIcon(const char *id) const;
890 	QIcon GetGroupIcon() const;
891 	QIcon GetSceneIcon() const;
892 
893 	OBSWeakSource copyFilter = nullptr;
894 
895 	void ShowStatusBarMessage(const QString &message);
896 
897 	static OBSData
898 	BackupScene(obs_scene_t *scene,
899 		    std::vector<obs_source_t *> *sources = nullptr);
900 	void CreateSceneUndoRedoAction(const QString &action_name,
901 				       OBSData undo_data, OBSData redo_data);
902 
903 	static inline OBSData
BackupScene(obs_source_t * scene_source,std::vector<obs_source_t * > * sources=nullptr)904 	BackupScene(obs_source_t *scene_source,
905 		    std::vector<obs_source_t *> *sources = nullptr)
906 	{
907 		obs_scene_t *scene = obs_scene_from_source(scene_source);
908 		return BackupScene(scene, sources);
909 	}
910 
911 	void CreateFilterPasteUndoRedoAction(const QString &text,
912 					     obs_source_t *source,
913 					     obs_data_array_t *undo_array,
914 					     obs_data_array_t *redo_array);
915 
916 protected:
917 	virtual void closeEvent(QCloseEvent *event) override;
918 	virtual void changeEvent(QEvent *event) override;
919 
920 private slots:
921 	void on_actionFullscreenInterface_triggered();
922 
923 	void on_actionShow_Recordings_triggered();
924 	void on_actionRemux_triggered();
925 	void on_action_Settings_triggered();
926 	void on_actionShowMissingFiles_triggered();
927 	void on_actionAdvAudioProperties_triggered();
928 	void AdvAudioPropsClicked();
929 	void AdvAudioPropsDestroyed();
930 	void on_actionShowLogs_triggered();
931 	void on_actionUploadCurrentLog_triggered();
932 	void on_actionUploadLastLog_triggered();
933 	void on_actionViewCurrentLog_triggered();
934 	void on_actionCheckForUpdates_triggered();
935 
936 	void on_actionShowCrashLogs_triggered();
937 	void on_actionUploadLastCrashLog_triggered();
938 
939 	void on_actionEditTransform_triggered();
940 	void on_actionCopyTransform_triggered();
941 	void on_actionPasteTransform_triggered();
942 	void on_actionRotate90CW_triggered();
943 	void on_actionRotate90CCW_triggered();
944 	void on_actionRotate180_triggered();
945 	void on_actionFlipHorizontal_triggered();
946 	void on_actionFlipVertical_triggered();
947 	void on_actionFitToScreen_triggered();
948 	void on_actionStretchToScreen_triggered();
949 	void on_actionCenterToScreen_triggered();
950 	void on_actionVerticalCenter_triggered();
951 	void on_actionHorizontalCenter_triggered();
952 
953 	void on_customContextMenuRequested(const QPoint &pos);
954 
955 	void on_scenes_currentItemChanged(QListWidgetItem *current,
956 					  QListWidgetItem *prev);
957 	void on_scenes_customContextMenuRequested(const QPoint &pos);
958 	void GridActionClicked();
959 	void on_actionAddScene_triggered();
960 	void on_actionRemoveScene_triggered();
961 	void on_actionSceneUp_triggered();
962 	void on_actionSceneDown_triggered();
963 	void on_sources_customContextMenuRequested(const QPoint &pos);
964 	void on_scenes_itemDoubleClicked(QListWidgetItem *item);
965 	void on_actionAddSource_triggered();
966 	void on_actionRemoveSource_triggered();
967 	void on_actionInteract_triggered();
968 	void on_actionSourceProperties_triggered();
969 	void on_actionSourceUp_triggered();
970 	void on_actionSourceDown_triggered();
971 
972 	void on_actionMoveUp_triggered();
973 	void on_actionMoveDown_triggered();
974 	void on_actionMoveToTop_triggered();
975 	void on_actionMoveToBottom_triggered();
976 
977 	void on_actionLockPreview_triggered();
978 
979 	void on_scalingMenu_aboutToShow();
980 	void on_actionScaleWindow_triggered();
981 	void on_actionScaleCanvas_triggered();
982 	void on_actionScaleOutput_triggered();
983 
984 	void on_streamButton_clicked();
985 	void on_recordButton_clicked();
986 	void VCamButtonClicked();
987 	void on_settingsButton_clicked();
988 	void Screenshot(OBSSource source_ = nullptr);
989 	void ScreenshotSelectedSource();
990 	void ScreenshotProgram();
991 	void ScreenshotScene();
992 
993 	void on_actionHelpPortal_triggered();
994 	void on_actionWebsite_triggered();
995 	void on_actionDiscord_triggered();
996 
997 	void on_preview_customContextMenuRequested(const QPoint &pos);
998 	void ProgramViewContextMenuRequested(const QPoint &pos);
999 	void PreviewDisabledMenu(const QPoint &pos);
1000 
1001 	void on_actionNewSceneCollection_triggered();
1002 	void on_actionDupSceneCollection_triggered();
1003 	void on_actionRenameSceneCollection_triggered();
1004 	void on_actionRemoveSceneCollection_triggered();
1005 	void on_actionImportSceneCollection_triggered();
1006 	void on_actionExportSceneCollection_triggered();
1007 
1008 	void on_actionNewProfile_triggered();
1009 	void on_actionDupProfile_triggered();
1010 	void on_actionRenameProfile_triggered();
1011 	void on_actionRemoveProfile_triggered(bool skipConfirmation = false);
1012 	void on_actionImportProfile_triggered();
1013 	void on_actionExportProfile_triggered();
1014 
1015 	void on_actionShowSettingsFolder_triggered();
1016 	void on_actionShowProfileFolder_triggered();
1017 
1018 	void on_actionAlwaysOnTop_triggered();
1019 
1020 	void on_toggleListboxToolbars_toggled(bool visible);
1021 	void on_toggleContextBar_toggled(bool visible);
1022 	void on_toggleStatusBar_toggled(bool visible);
1023 	void on_toggleSourceIcons_toggled(bool visible);
1024 
1025 	void on_transitions_currentIndexChanged(int index);
1026 	void RemoveTransitionClicked();
1027 	void on_transitionProps_clicked();
1028 	void on_transitionDuration_valueChanged(int value);
1029 	void on_tbar_position_valueChanged(int value);
1030 
1031 	void on_actionShowTransitionProperties_triggered();
1032 	void on_actionHideTransitionProperties_triggered();
1033 
1034 	void on_modeSwitch_clicked();
1035 
1036 	// Source Context Buttons
1037 	void on_sourcePropertiesButton_clicked();
1038 	void on_sourceFiltersButton_clicked();
1039 	void on_sourceInteractButton_clicked();
1040 
1041 	void on_autoConfigure_triggered();
1042 	void on_stats_triggered();
1043 
1044 	void on_resetUI_triggered();
1045 	void on_lockUI_toggled(bool lock);
1046 
1047 	void PauseToggled();
1048 
1049 	void logUploadFinished(const QString &text, const QString &error);
1050 	void crashUploadFinished(const QString &text, const QString &error);
1051 	void openLogDialog(const QString &text, const bool crash);
1052 
1053 	void updateCheckFinished();
1054 
1055 	void AddSourceFromAction();
1056 
1057 	void MoveSceneToTop();
1058 	void MoveSceneToBottom();
1059 
1060 	void EditSceneName();
1061 	void EditSceneItemName();
1062 
1063 	void SceneNameEdited(QWidget *editor,
1064 			     QAbstractItemDelegate::EndEditHint endHint);
1065 
1066 	void OpenSceneFilters();
1067 	void OpenFilters(OBSSource source = nullptr);
1068 	void OpenProperties(OBSSource source = nullptr);
1069 
1070 	void EnablePreviewDisplay(bool enable);
1071 	void TogglePreview();
1072 
1073 	void NudgeUp();
1074 	void NudgeDown();
1075 	void NudgeLeft();
1076 	void NudgeRight();
1077 
1078 	void OpenStudioProgramProjector();
1079 	void OpenPreviewProjector();
1080 	void OpenSourceProjector();
1081 	void OpenMultiviewProjector();
1082 	void OpenSceneProjector();
1083 
1084 	void OpenStudioProgramWindow();
1085 	void OpenPreviewWindow();
1086 	void OpenSourceWindow();
1087 	void OpenMultiviewWindow();
1088 	void OpenSceneWindow();
1089 
1090 	void DeferredSysTrayLoad(int requeueCount);
1091 
1092 	void StackedMixerAreaContextMenuRequested();
1093 
1094 	void ResizeOutputSizeOfSource();
1095 
1096 public slots:
1097 	void on_actionResetTransform_triggered();
1098 
1099 	bool StreamingActive();
1100 	bool RecordingActive();
1101 	bool ReplayBufferActive();
1102 
1103 	void ClearContextBar();
1104 	void UpdateContextBar(bool force = false);
1105 	void UpdateContextBarDeferred(bool force = false);
1106 
1107 public:
1108 	explicit OBSBasic(QWidget *parent = 0);
1109 	virtual ~OBSBasic();
1110 
1111 	virtual void OBSInit() override;
1112 
1113 	virtual config_t *Config() const override;
1114 
1115 	virtual int GetProfilePath(char *path, size_t size,
1116 				   const char *file) const override;
1117 
1118 	static void InitBrowserPanelSafeBlock();
1119 
1120 private:
1121 	std::unique_ptr<Ui::OBSBasic> ui;
1122 };
1123 
1124 class SceneRenameDelegate : public QStyledItemDelegate {
1125 	Q_OBJECT
1126 
1127 public:
1128 	SceneRenameDelegate(QObject *parent);
1129 	virtual void setEditorData(QWidget *editor,
1130 				   const QModelIndex &index) const override;
1131 
1132 protected:
1133 	virtual bool eventFilter(QObject *editor, QEvent *event) override;
1134 };
1135