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 "ProfileBox.h"
24 
25 #if SSR_USE_ALSA
26 #include "ALSAInput.h"
27 #endif
28 #if SSR_USE_PULSEAUDIO
29 #include "PulseAudioInput.h"
30 #endif
31 
32 class QComboBoxWithSignal : public QComboBox {
33 	Q_OBJECT
34 
35 public:
36 	QComboBoxWithSignal(QWidget* parent);
37 
38 	virtual void showPopup() override;
39 	virtual void hidePopup() override;
40 
41 signals:
42 	void popupShown();
43 	void popupHidden();
44 
45 };
46 
47 class QSpinBoxWithSignal : public QSpinBox {
48 	Q_OBJECT
49 
50 public:
51 	QSpinBoxWithSignal(QWidget* parent);
52 
53 	virtual void focusInEvent(QFocusEvent* event) override;
54 	virtual void focusOutEvent(QFocusEvent* event) override;
55 
56 signals:
57 	void focusIn();
58 	void focusOut();
59 
60 };
61 
62 class ScreenLabelWindow : public QWidget {
63 	Q_OBJECT
64 
65 private:
66 	QString m_text;
67 	QFont m_font;
68 
69 public:
70 	ScreenLabelWindow(QWidget* parent, const QString& text);
71 
72 protected:
73 	virtual void paintEvent(QPaintEvent* event) override;
74 
75 };
76 
77 class RecordingFrameWindow : public QWidget {
78 	Q_OBJECT
79 
80 private:
81 	bool m_outside;
82 	QPixmap m_texture;
83 
84 public:
85 	static constexpr int BORDER_WIDTH = 4;
86 
87 public:
88 	RecordingFrameWindow(QWidget* parent, bool outside);
89 
90 	void SetRectangle(const QRect& r);
91 
92 private:
93 	void UpdateMask();
94 
95 protected:
96 	virtual void resizeEvent(QResizeEvent* event) override;
97 	virtual void paintEvent(QPaintEvent* event) override;
98 
99 };
100 
101 class MainWindow;
102 
103 class PageInput : public QWidget {
104 	Q_OBJECT
105 
106 public:
107 	enum enum_video_area {
108 		VIDEO_AREA_SCREEN,
109 		VIDEO_AREA_FIXED,
110 		VIDEO_AREA_CURSOR,
111 #if SSR_USE_OPENGL_RECORDING
112 		VIDEO_AREA_GLINJECT,
113 #endif
114 #if SSR_USE_V4L2
115 		VIDEO_AREA_V4L2,
116 #endif
117 		VIDEO_AREA_COUNT // must be last
118 	};
119 	enum enum_audio_backend {
120 #if SSR_USE_ALSA
121 		AUDIO_BACKEND_ALSA,
122 #endif
123 #if SSR_USE_PULSEAUDIO
124 		AUDIO_BACKEND_PULSEAUDIO,
125 #endif
126 #if SSR_USE_JACK
127 		AUDIO_BACKEND_JACK,
128 #endif
129 		AUDIO_BACKEND_COUNT // must be last
130 	};
131 
132 private:
133 	MainWindow *m_main_window;
134 
135 	bool m_grabbing, m_selecting_window;
136 	std::unique_ptr<RecordingFrameWindow> m_rubber_band, m_recording_frame;
137 	QRect m_rubber_band_rect, m_select_window_outer_rect, m_select_window_inner_rect;
138 
139 #if SSR_USE_ALSA
140 	std::vector<ALSAInput::Source> m_alsa_sources;
141 #endif
142 #if SSR_USE_PULSEAUDIO
143 	bool m_pulseaudio_available;
144 	std::vector<PulseAudioInput::Source> m_pulseaudio_sources;
145 #endif
146 
147 #if SSR_USE_OPENGL_RECORDING
148 	QString m_glinject_channel;
149 	bool m_glinject_relax_permissions;
150 	QString m_glinject_command, m_glinject_working_directory;
151 	bool m_glinject_auto_launch;
152 	bool m_glinject_limit_fps;
153 #endif
154 
155 	std::vector<ScreenLabelWindow*> m_screen_labels;
156 
157 	ProfileBox *m_profile_box;
158 
159 	QButtonGroup *m_buttongroup_video_area;
160 	QComboBoxWithSignal *m_combobox_screens;
161 	QCheckBox *m_checkbox_follow_fullscreen;
162 	QPushButton *m_pushbutton_video_select_rectangle, *m_pushbutton_video_select_window;
163 #if SSR_USE_OPENGL_RECORDING
164 	QPushButton *m_pushbutton_video_opengl_settings;
165 #endif
166 #if SSR_USE_V4L2
167 	QLineEdit *m_lineedit_v4l2_device;
168 #endif
169 	QLabel *m_label_video_x, *m_label_video_y, *m_label_video_w, *m_label_video_h;
170 	QSpinBoxWithSignal *m_spinbox_video_x, *m_spinbox_video_y, *m_spinbox_video_w, *m_spinbox_video_h;
171 	QSpinBox *m_spinbox_video_frame_rate;
172 	QCheckBox *m_checkbox_scale;
173 	QLabel *m_label_video_scaled_w, *m_label_video_scaled_h;
174 	QSpinBox *m_spinbox_video_scaled_w, *m_spinbox_video_scaled_h;
175 	QCheckBox *m_checkbox_record_cursor;
176 
177 	QCheckBox *m_checkbox_audio_enable;
178 	QLabel *m_label_audio_backend;
179 	QComboBox *m_combobox_audio_backend;
180 #if SSR_USE_ALSA
181 	QLabel *m_label_alsa_source;
182 	QComboBox *m_combobox_alsa_source;
183 	QPushButton *m_pushbutton_alsa_refresh;
184 #endif
185 #if SSR_USE_PULSEAUDIO
186 	QLabel *m_label_pulseaudio_source;
187 	QComboBox *m_combobox_pulseaudio_source;
188 	QPushButton *m_pushbutton_pulseaudio_refresh;
189 #endif
190 #if SSR_USE_JACK
191 	QCheckBox *m_checkbox_jack_connect_system_capture, *m_checkbox_jack_connect_system_playback;
192 #endif
193 
194 public:
195 	PageInput(MainWindow* main_window);
196 
197 	void LoadSettings(QSettings* settings);
198 	void SaveSettings(QSettings* settings);
199 
200 private:
201 	static void LoadProfileSettingsCallback(QSettings* settings, void* userdata);
202 	static void SaveProfileSettingsCallback(QSettings* settings, void* userdata);
203 	void LoadProfileSettings(QSettings* settings);
204 	void SaveProfileSettings(QSettings* settings);
205 
206 public:
207 	bool Validate();
208 
209 #if SSR_USE_ALSA
210 	QString GetALSASourceName();
211 #endif
212 #if SSR_USE_PULSEAUDIO
213 	QString GetPulseAudioSourceName();
214 #endif
215 
216 private:
217 #if SSR_USE_ALSA
218 	unsigned int FindALSASource(const QString& name);
219 #endif
220 #if SSR_USE_PULSEAUDIO
221 	unsigned int FindPulseAudioSource(const QString& name);
222 #endif
223 
224 protected:
225 	virtual void mousePressEvent(QMouseEvent* event) override;
226 	virtual void mouseReleaseEvent(QMouseEvent* event) override;
227 	virtual void mouseMoveEvent(QMouseEvent* event) override;
228 	virtual void keyPressEvent(QKeyEvent* event) override;
229 
230 private:
231 	void StartGrabbing();
232 	void StopGrabbing();
233 	void UpdateRubberBand();
234 	void SetVideoAreaFromRubberBand();
235 
236 	void LoadScreenConfigurations();
237 #if SSR_USE_ALSA
238 	void LoadALSASources();
239 #endif
240 #if SSR_USE_PULSEAUDIO
241 	void LoadPulseAudioSources();
242 #endif
243 
244 public slots:
245 	void OnUpdateRecordingFrame();
246 	void OnUpdateVideoAreaFields();
247 	void OnUpdateVideoScaleFields();
248 	void OnUpdateAudioFields();
249 
250 private slots:
251 	void OnFocusChange(QWidget* old, QWidget* now);
252 #if QT_VERSION_MAJOR >= 5
253 	void OnScreenAdded(QScreen* screen);
254 #endif
255 	void OnUpdateScreenConfiguration();
256 #if SSR_USE_ALSA
257 	void OnUpdateALSASources();
258 #endif
259 #if SSR_USE_PULSEAUDIO
260 	void OnUpdatePulseAudioSources();
261 #endif
262 	void OnIdentifyScreens();
263 	void OnStopIdentifyScreens();
264 	void OnStartSelectRectangle();
265 	void OnStartSelectWindow();
266 #if SSR_USE_OPENGL_RECORDING
267 	void OnGLInjectDialog();
268 #endif
269 	void OnContinue();
270 
271 public:
GetProfile()272 	inline unsigned int GetProfile() { return m_profile_box->GetProfile(); }
GetVideoArea()273 	inline enum_video_area GetVideoArea() { return (enum_video_area) clamp(m_buttongroup_video_area->checkedId(), 0, VIDEO_AREA_COUNT - 1); }
GetVideoAreaScreen()274 	inline unsigned int GetVideoAreaScreen() { return m_combobox_screens->currentIndex(); }
GetVideoAreaFollowFullscreen()275 	inline bool GetVideoAreaFollowFullscreen() { return m_checkbox_follow_fullscreen->isChecked(); }
276 #if SSR_USE_V4L2
GetVideoV4L2Device()277 	inline QString GetVideoV4L2Device() { return m_lineedit_v4l2_device->text(); }
278 #endif
GetVideoX()279 	inline unsigned int GetVideoX() { return m_spinbox_video_x->value(); }
GetVideoY()280 	inline unsigned int GetVideoY() { return m_spinbox_video_y->value(); }
GetVideoW()281 	inline unsigned int GetVideoW() { return m_spinbox_video_w->value(); }
GetVideoH()282 	inline unsigned int GetVideoH() { return m_spinbox_video_h->value(); }
GetVideoFrameRate()283 	inline unsigned int GetVideoFrameRate() { return m_spinbox_video_frame_rate->value(); }
GetVideoScalingEnabled()284 	inline bool GetVideoScalingEnabled() { return m_checkbox_scale->isChecked(); }
GetVideoScaledW()285 	inline unsigned int GetVideoScaledW() { return m_spinbox_video_scaled_w->value(); }
GetVideoScaledH()286 	inline unsigned int GetVideoScaledH() { return m_spinbox_video_scaled_h->value(); }
GetVideoRecordCursor()287 	inline bool GetVideoRecordCursor() { return m_checkbox_record_cursor->isChecked(); }
GetAudioEnabled()288 	inline bool GetAudioEnabled() { return m_checkbox_audio_enable->isChecked(); }
GetAudioBackend()289 	inline enum_audio_backend GetAudioBackend() { return (enum_audio_backend) clamp(m_combobox_audio_backend->currentIndex(), 0, AUDIO_BACKEND_COUNT - 1); }
290 #if SSR_USE_ALSA
GetALSASource()291 	inline unsigned int GetALSASource() { return clamp(m_combobox_alsa_source->currentIndex(), 0, (int) m_alsa_sources.size() - 1); }
292 #endif
293 #if SSR_USE_PULSEAUDIO
GetPulseAudioSource()294 	inline unsigned int GetPulseAudioSource() { return clamp(m_combobox_pulseaudio_source->currentIndex(), 0, (int) m_pulseaudio_sources.size() - 1); }
295 #endif
296 #if SSR_USE_JACK
GetJackConnectSystemCapture()297 	inline bool GetJackConnectSystemCapture() { return m_checkbox_jack_connect_system_capture->isChecked(); }
GetJackConnectSystemPlayback()298 	inline bool GetJackConnectSystemPlayback() { return m_checkbox_jack_connect_system_playback->isChecked(); }
299 #endif
300 #if SSR_USE_OPENGL_RECORDING
GetGLInjectChannel()301 	inline QString GetGLInjectChannel() { return m_glinject_channel; }
GetGLInjectRelaxPermissions()302 	inline bool GetGLInjectRelaxPermissions() { return m_glinject_relax_permissions; }
GetGLInjectCommand()303 	inline QString GetGLInjectCommand() { return m_glinject_command; }
GetGLInjectWorkingDirectory()304 	inline QString GetGLInjectWorkingDirectory() { return m_glinject_working_directory; }
GetGLInjectAutoLaunch()305 	inline bool GetGLInjectAutoLaunch() { return m_glinject_auto_launch; }
GetGLInjectLimitFPS()306 	inline bool GetGLInjectLimitFPS() { return m_glinject_limit_fps; }
307 #endif
308 
SetProfile(unsigned int profile)309 	inline void SetProfile(unsigned int profile) { m_profile_box->SetProfile(profile); }
SetVideoArea(enum_video_area area)310 	inline void SetVideoArea(enum_video_area area) { QAbstractButton *b = m_buttongroup_video_area->button(area); if(b != NULL) b->setChecked(true); }
SetVideoAreaScreen(unsigned int screen)311 	inline void SetVideoAreaScreen(unsigned int screen) { m_combobox_screens->setCurrentIndex(clamp(screen, 0u, (unsigned int) m_combobox_screens->count() - 1)); }
SetVideoAreaFollowFullscreen(bool follow_fulscreen)312 	inline void SetVideoAreaFollowFullscreen(bool follow_fulscreen) { m_checkbox_follow_fullscreen->setChecked(follow_fulscreen); }
313 #if SSR_USE_V4L2
SetVideoV4L2Device(const QString & device)314 	inline void SetVideoV4L2Device(const QString& device) { m_lineedit_v4l2_device->setText(device); }
315 #endif
SetVideoX(unsigned int x)316 	inline void SetVideoX(unsigned int x) { m_spinbox_video_x->setValue(x); }
SetVideoY(unsigned int y)317 	inline void SetVideoY(unsigned int y) { m_spinbox_video_y->setValue(y); }
SetVideoW(unsigned int w)318 	inline void SetVideoW(unsigned int w) { m_spinbox_video_w->setValue(w); }
SetVideoH(unsigned int h)319 	inline void SetVideoH(unsigned int h) { m_spinbox_video_h->setValue(h); }
SetVideoFrameRate(unsigned int frame_rate)320 	inline void SetVideoFrameRate(unsigned int frame_rate) { m_spinbox_video_frame_rate->setValue(frame_rate); }
SetVideoScalingEnabled(bool enable)321 	inline void SetVideoScalingEnabled(bool enable) { m_checkbox_scale->setChecked(enable); }
SetVideoScaledW(unsigned int scaled_w)322 	inline void SetVideoScaledW(unsigned int scaled_w) { m_spinbox_video_scaled_w->setValue(scaled_w); }
SetVideoScaledH(unsigned int scaled_h)323 	inline void SetVideoScaledH(unsigned int scaled_h) { m_spinbox_video_scaled_h->setValue(scaled_h); }
SetVideoRecordCursor(bool show)324 	inline void SetVideoRecordCursor(bool show) { m_checkbox_record_cursor->setChecked(show); }
SetAudioEnabled(bool enable)325 	inline void SetAudioEnabled(bool enable) { m_checkbox_audio_enable->setChecked(enable); }
SetAudioBackend(enum_audio_backend backend)326 	inline void SetAudioBackend(enum_audio_backend backend) { m_combobox_audio_backend->setCurrentIndex(clamp((int) backend, 0, AUDIO_BACKEND_COUNT - 1)); }
327 #if SSR_USE_ALSA
SetALSASource(unsigned int source)328 	inline void SetALSASource(unsigned int source) { m_combobox_alsa_source->setCurrentIndex(clamp(source, 0u, (unsigned int) m_alsa_sources.size() - 1)); }
329 #endif
330 #if SSR_USE_PULSEAUDIO
SetPulseAudioSource(unsigned int source)331 	inline void SetPulseAudioSource(unsigned int source) { m_combobox_pulseaudio_source->setCurrentIndex(clamp(source, 0u, (unsigned int) m_pulseaudio_sources.size() - 1)); }
332 #endif
333 #if SSR_USE_JACK
SetJackConnectSystemCapture(bool connect)334 	inline void SetJackConnectSystemCapture(bool connect) { m_checkbox_jack_connect_system_capture->setChecked(connect); }
SetJackConnectSystemPlayback(bool connect)335 	inline void SetJackConnectSystemPlayback(bool connect) { m_checkbox_jack_connect_system_playback->setChecked(connect); }
336 #endif
337 #if SSR_USE_OPENGL_RECORDING
SetGLInjectChannel(const QString & channel)338 	inline void SetGLInjectChannel(const QString& channel) { m_glinject_channel = channel; }
SetGLInjectRelaxPermissions(bool relax_permissions)339 	inline void SetGLInjectRelaxPermissions(bool relax_permissions) { m_glinject_relax_permissions = relax_permissions; }
SetGLInjectCommand(const QString & command)340 	inline void SetGLInjectCommand(const QString& command) { m_glinject_command = command; }
SetGLInjectWorkingDirectory(const QString & glinject_working_directory)341 	inline void SetGLInjectWorkingDirectory(const QString& glinject_working_directory) { m_glinject_working_directory = glinject_working_directory; }
SetGLInjectAutoLaunch(bool auto_launch)342 	inline void SetGLInjectAutoLaunch(bool auto_launch) { m_glinject_auto_launch = auto_launch; }
SetGLInjectLimitFPS(bool limit_fps)343 	inline void SetGLInjectLimitFPS(bool limit_fps) { m_glinject_limit_fps = limit_fps; }
344 #endif
345 
346 };
347