1 /*
2 Copyright (c) 2012-2020 Maarten Baert <maarten-baert@hotmail.com>
3 
4 This file is part of SimpleScreenRecorder.
5 
6 SimpleScreenRecorder is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 SimpleScreenRecorder is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with SimpleScreenRecorder.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 #include "Global.h"
22 
23 #include "Logger.h"
24 #include "PageInput.h"
25 #include "OutputSettings.h"
26 #include "OutputManager.h"
27 #include "ElidedLabel.h"
28 #include "HotkeyListener.h"
29 #include "DialogRecordSchedule.h"
30 
31 class MainWindow;
32 
33 class Muxer;
34 class VideoEncoder;
35 class AudioEncoder;
36 class Synchronizer;
37 class X11Input;
38 #if SSR_USE_OPENGL_RECORDING
39 class GLInjectLauncher;
40 class GLInjectInput;
41 #endif
42 #if SSR_USE_V4L2
43 class V4L2Input;
44 #endif
45 #if SSR_USE_ALSA
46 class ALSAInput;
47 #endif
48 #if SSR_USE_PULSEAUDIO
49 class PulseAudioInput;
50 #endif
51 #if SSR_USE_JACK
52 class JACKInput;
53 #endif
54 #if SSR_USE_ALSA
55 class SimpleSynth;
56 #endif
57 class VideoPreviewer;
58 class AudioPreviewer;
59 
60 class PageRecord : public QWidget {
61 	Q_OBJECT
62 
63 private:
64 	static constexpr int PRIORITY_RECORD = 0, PRIORITY_PREVIEW = -1;
65 
66 private:
67 	MainWindow *m_main_window;
68 
69 	bool m_page_started, m_input_started, m_output_started, m_previewing;
70 	bool m_recorded_something, m_wait_saving, m_error_occurred;
71 
72 	bool m_schedule_active;
73 	unsigned int m_schedule_position;
74 	enum_schedule_time_zone m_schedule_time_zone;
75 	std::vector<ScheduleEntry> m_schedule_entries;
76 
77 	PageInput::enum_video_area m_video_area;
78 	bool m_video_area_follow_fullscreen;
79 #if SSR_USE_V4L2
80 	QString m_v4l2_device;
81 #endif
82 	unsigned int m_video_x, m_video_y, m_video_in_width, m_video_in_height;
83 	unsigned int m_video_frame_rate;
84 	bool m_video_scaling;
85 	unsigned int m_video_scaled_width, m_video_scaled_height;
86 	bool m_video_record_cursor;
87 	bool m_audio_enabled;
88 	unsigned int m_audio_channels, m_audio_sample_rate;
89 	PageInput::enum_audio_backend m_audio_backend;
90 #if SSR_USE_ALSA
91 	QString m_alsa_source;
92 #endif
93 #if SSR_USE_PULSEAUDIO
94 	QString m_pulseaudio_source;
95 #endif
96 
97 	OutputSettings m_output_settings;
98 	std::unique_ptr<OutputManager> m_output_manager;
99 
100 	QString m_file_base;
101 	QString m_file_protocol;
102 	bool m_separate_files, m_add_timestamp;
103 
104 	std::unique_ptr<X11Input> m_x11_input;
105 #if SSR_USE_OPENGL_RECORDING
106 	std::unique_ptr<GLInjectInput> m_gl_inject_input;
107 #endif
108 #if SSR_USE_V4L2
109 	std::unique_ptr<V4L2Input> m_v4l2_input;
110 #endif
111 #if SSR_USE_ALSA
112 	std::unique_ptr<ALSAInput> m_alsa_input;
113 #endif
114 #if SSR_USE_PULSEAUDIO
115 	std::unique_ptr<PulseAudioInput> m_pulseaudio_input;
116 #endif
117 #if SSR_USE_JACK
118 	std::unique_ptr<JACKInput> m_jack_input;
119 #endif
120 
121 #if SSR_USE_ALSA
122 	std::unique_ptr<SimpleSynth> m_simple_synth;
123 	int64_t m_last_error_sound;
124 #endif
125 
126 	HotkeyCallback m_hotkey_start_pause;
127 
128 	QPushButton *m_pushbutton_record;
129 	QLabel *m_label_schedule_status;
130 	QPushButton *m_pushbutton_schedule_activate, *m_pushbutton_schedule_edit;
131 
132 	QCheckBox *m_checkbox_hotkey_enable;
133 #if SSR_USE_ALSA
134 	QCheckBox *m_checkbox_sound_notifications_enable;
135 #endif
136 	QCheckBox *m_checkbox_hotkey_ctrl, *m_checkbox_hotkey_shift, *m_checkbox_hotkey_alt, *m_checkbox_hotkey_super;
137 	QComboBox *m_combobox_hotkey_key;
138 
139 	QLabel *m_label_info_total_time, *m_label_info_frame_rate_in, *m_label_info_frame_rate_out, *m_label_info_size_in, *m_label_info_size_out;
140 	ElidedLabel *m_label_info_file_name;
141 	QLabel *m_label_info_file_size, *m_label_info_bit_rate;
142 	QCheckBox *m_checkbox_show_recording_area;
143 
144 	QStackedLayout *m_stacked_layout_preview;
145 	QWidget *m_preview_page1, *m_preview_page2;
146 	QSpinBox *m_spinbox_preview_frame_rate;
147 	VideoPreviewer *m_video_previewer;
148 	QLabel *m_label_mic_icon;
149 	AudioPreviewer *m_audio_previewer;
150 	QPushButton *m_pushbutton_preview_start_stop;
151 
152 	QTextEdit *m_textedit_log;
153 
154 	QSystemTrayIcon *m_systray_icon;
155 	QAction *m_systray_action_start_pause, *m_systray_action_cancel, *m_systray_action_save;
156 	QAction *m_systray_action_show_hide, *m_systray_action_quit;
157 
158 	QSocketNotifier *m_stdin_notifier;
159 	QByteArray m_stdin_buffer;
160 	bool m_stdin_reentrant;
161 
162 	QTimer *m_timer_schedule, *m_timer_update_info;
163 
164 	std::unique_ptr<RecordingFrameWindow> m_recording_frame;
165 
166 public:
167 	PageRecord(MainWindow* main_window);
168 	~PageRecord();
169 
170 	// Called when the user tries to close the program. If this function returns true, the command will be blocked.
171 	// This is used to display a warning if the user is about to close the program during a recording.
172 	bool ShouldBlockClose();
173 
174 	// Called when the main window is shown/hidden (to update the system tray).
175 	void UpdateShowHide();
176 
177 	void LoadSettings(QSettings* settings);
178 	void SaveSettings(QSettings* settings);
179 
180 	bool TryStartPage();
181 	void StartPage();
182 	void StopPage(bool save);
183 	void StartOutput();
184 	void StopOutput(bool final);
185 	void StartInput();
186 	void StopInput();
187 
188 private:
189 	void FinishOutput();
190 	void UpdateInput();
191 	void UpdateSysTray();
192 	void UpdateRecordButton();
193 	void UpdateSchedule();
194 	void UpdatePreview();
195 
196 	QString ReadStdinCommand();
197 
198 public:
GetScheduleTimeZone()199 	inline enum_schedule_time_zone GetScheduleTimeZone() { return m_schedule_time_zone; }
GetScheduleEntries()200 	inline std::vector<ScheduleEntry> GetScheduleEntries() { return m_schedule_entries; }
IsHotkeyEnabled()201 	inline bool IsHotkeyEnabled() { return m_checkbox_hotkey_enable->isChecked(); }
IsHotkeyCtrlEnabled()202 	inline bool IsHotkeyCtrlEnabled() { return m_checkbox_hotkey_ctrl->isChecked(); }
IsHotkeyShiftEnabled()203 	inline bool IsHotkeyShiftEnabled() { return m_checkbox_hotkey_shift->isChecked(); }
IsHotkeyAltEnabled()204 	inline bool IsHotkeyAltEnabled() { return m_checkbox_hotkey_alt->isChecked(); }
IsHotkeySuperEnabled()205 	inline bool IsHotkeySuperEnabled() { return m_checkbox_hotkey_super->isChecked(); }
GetHotkeyKey()206 	inline unsigned int GetHotkeyKey() { return m_combobox_hotkey_key->currentIndex(); }
207 #if SSR_USE_ALSA
AreSoundNotificationsEnabled()208 	inline bool AreSoundNotificationsEnabled() { return m_checkbox_sound_notifications_enable->isChecked(); }
209 #endif
GetShowRecordingArea()210 	inline bool GetShowRecordingArea() { return m_checkbox_show_recording_area->isChecked(); }
GetPreviewFrameRate()211 	inline unsigned int GetPreviewFrameRate() { return m_spinbox_preview_frame_rate->value(); }
212 
SetScheduleTimeZone(enum_schedule_time_zone time_zone)213 	inline void SetScheduleTimeZone(enum_schedule_time_zone time_zone) { m_schedule_time_zone = (enum_schedule_time_zone) clamp((unsigned int) time_zone, 0u, (unsigned int) SCHEDULE_TIME_ZONE_COUNT - 1); }
SetScheduleEntries(const std::vector<ScheduleEntry> & schedule)214 	inline void SetScheduleEntries(const std::vector<ScheduleEntry>& schedule) { m_schedule_entries = schedule; }
SetHotkeyEnabled(bool enable)215 	inline void SetHotkeyEnabled(bool enable) { m_checkbox_hotkey_enable->setChecked(enable); }
SetHotkeyCtrlEnabled(bool enable)216 	inline void SetHotkeyCtrlEnabled(bool enable) { m_checkbox_hotkey_ctrl->setChecked(enable); }
SetHotkeyShiftEnabled(bool enable)217 	inline void SetHotkeyShiftEnabled(bool enable) { m_checkbox_hotkey_shift->setChecked(enable); }
SetHotkeyAltEnabled(bool enable)218 	inline void SetHotkeyAltEnabled(bool enable) { m_checkbox_hotkey_alt->setChecked(enable); }
SetHotkeySuperEnabled(bool enable)219 	inline void SetHotkeySuperEnabled(bool enable) { m_checkbox_hotkey_super->setChecked(enable); }
SetHotkeyKey(unsigned int key)220 	inline void SetHotkeyKey(unsigned int key) { m_combobox_hotkey_key->setCurrentIndex(clamp(key, 0u, 25u)); }
221 #if SSR_USE_ALSA
SetSoundNotificationsEnabled(bool enable)222 	inline void SetSoundNotificationsEnabled(bool enable) { m_checkbox_sound_notifications_enable->setChecked(enable); }
223 #endif
SetShowRecordingArea(bool enable)224 	inline void SetShowRecordingArea(bool enable) { m_checkbox_show_recording_area->setChecked(enable); }
SetPreviewFrameRate(unsigned int frame_rate)225 	inline void SetPreviewFrameRate(unsigned int frame_rate) { m_spinbox_preview_frame_rate->setValue(frame_rate); }
226 
227 public slots:
228 	void OnUpdateHotkeyFields();
229 	void OnUpdateHotkey();
230 #if SSR_USE_ALSA
231 	void OnUpdateSoundNotifications();
232 #endif
233 	void OnUpdateRecordingFrame();
234 
235 public slots:
236 	void OnRecordStart();
237 	void OnRecordPause();
238 	void OnRecordStartPause();
239 	void OnRecordCancel(bool confirm = true);
240 	void OnRecordSave(bool confirm = true);
241 	void OnScheduleTimer();
242 	void OnScheduleActivate();
243 	void OnScheduleDeactivate();
244 	void OnScheduleActivateDeactivate();
245 	void OnScheduleEdit();
246 	void OnPreviewStartStop();
247 
248 private slots:
249 	void OnStdin();
250 	void OnUpdateInformation();
251 	void OnNewLogLine(Logger::enum_type type, QString string);
252 
253 };
254