summaryrefslogtreecommitdiffstats
path: root/pica-client/dialogs/settingsdialog.h
blob: b879a74cfcd0fe13d334e6382c06e27b59268c3e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
	(c) Copyright  2012 - 2018 Anton Sviridenko
	https://picapica.im

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, version 3.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H

#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QSpinBox>
#include <QRadioButton>
#include <QComboBox>
#include <QCheckBox>
#include <QLabel>
#include <QThread>
#include <QImage>
#include <QList>
#include <QTimer>
#include <QElapsedTimer>
#include "../mediadevice.h"
#include "../audiodevice.h"
#include "../videodevice.h"
#include "../toneplayer/toneplayer.h"
#ifdef HAVE_VAAPI
#include "../vaapi.h"
#endif

class SettingsDialog : public QDialog
{
	Q_OBJECT
public:
	explicit SettingsDialog(QWidget *parent = 0);
	~SettingsDialog();

signals:

public slots:
private slots:

private:
	QRadioButton *rbDisableDirectConns;
	QRadioButton *rbEnableOutgoingConns;
	QRadioButton *rbEnableIncomingConns;
#ifdef HAVE_LIBMINIUPNPC
	QCheckBox *cbEnableUPnP;
#endif

	QComboBox *addr;
	QSpinBox *publicPort;
	QSpinBox *localPort;

	QRadioButton *rbMLPProhibit;
	QRadioButton *rbMLPReplace;
	QRadioButton *rbMLPAllowMultiple;

	QComboBox *audioCaptureDev;
	QComboBox *audioPlaybackDev;
	QComboBox *audioRingDev;

	// Which audio API to go through. Only Linux has a choice worth offering
	// (ALSA or PulseAudio, the latter covering PipeWire's PulseAudio
	// interface too), so elsewhere this stays null and no widget is built.
	// The member and its slot are declared unconditionally all the same:
	// moc runs its own preprocessor and would not see a platform #ifdef, so
	// a slot hidden behind one ends up declared but never generated.
	QComboBox *audioDriver;

	// Whether to run our own acoustic echo cancellation. Ignored when the
	// platform provides one - see AudioDevice::PlatformDriverName().
	QCheckBox *cbEchoCancel;
	QCheckBox *cbAutoCaptureGain;

	QComboBox *videoDev;
	QPushButton *videoDevRefresh;

	// Local audio pipeline test: a few seconds of the selected microphone are
	// captured and encoded, then decoded again and played back through the
	// selected playback device - the same path a call takes, minus the
	// network. Recording and playback are deliberately kept apart in time
	// rather than looped back live, which would howl with acoustic feedback
	// when the test runs on speakers.
	QPushButton *btAudioTest;
	QLabel *audioTestStatus;
	AudioDevice *testMic;
	AudioDevice *testSpeaker;
	QThread testMicThread;
	QThread testSpeakerThread;

	enum AudioTestState
	{
		AudioTestIdle,
		AudioTestRecording,
		AudioTestPlaying
	};

	AudioTestState audioTestState;
	// What the microphone and playback devices reported negotiating, shown
	// with the result. Same idea as videoTestPathReport.
	QString audioTestPathReport;
	// The recording, as encoded packets, and how far playback has fed it.
	QList<QByteArray> audioTestPackets;
	int audioTestPlaybackPos;
	// Members rather than QTimer::singleShot() calls so that stopping a test
	// cancels them - otherwise a timer left over from an aborted run would
	// fire into the next one.
	QTimer *audioTestRecordTimer;
	QTimer *audioTestPlaybackTimer;
	// Playback is paced against this rather than against the number of times
	// the timer has fired - see audioTestFeedPacket().
	QElapsedTimer audioTestPlaybackClock;
	QTimer *audioTestDrainTimer;

	void stopAudioTest();
	void startAudioTestPlayback();

	// Ring device test: plays the incoming call bell through the selected
	// ring device, using the same TonePlayer an actual incoming call uses.
	// TonePlayer::play() blocks its thread for the length of the tone
	// sequence, hence the dedicated thread.
	QPushButton *btRingTest;
	QLabel *ringTestStatus;
	TonePlayer *ringTestPlayer;
	QThread ringTestPlayerThread;
	bool ringTestRunning;

	// Local video pipeline test: frames from the selected camera are
	// encoded, split into protocol sized fragments, reassembled and decoded
	// again, then shown in videoPreview - the same path a call takes, minus
	// the network, so the whole chain can be checked from this dialog.
	QPushButton *btVideoTest;
	QLabel *videoPreview;
	// Shown under the preview: the format the camera settled on, and whether
	// the GPU or the CPU ended up doing the encoding and decoding.
	QLabel *videoTestStatus;
	QString videoTestFormat;
	QString videoTestPathReport;
	QCheckBox *cbPreferCompressed;
#ifdef HAVE_VAAPI
	QCheckBox *cbVaapiEncoding;
	QCheckBox *cbVaapiDecoding;
	QCheckBox *cbVaapiRendering;
	// Shown in place of videoPreview while frames are being drawn straight
	// from GPU memory; only one of the two is ever visible.
	VaapiRenderWidget *videoPreviewGpu;
#endif
	VideoDevice *testCam;
	VideoDevice *testDecoder;
	QThread testCamThread;
	QThread testDecoderThread;
	VideoFrameAssembler testAssembler;
	// Counter part of the sequence number handed to testAssembler, kept the
	// same way AudioVideoCallController keeps it for a real call.
	quint16 testVideoSeq;
	bool videoTestRunning;

	void stopVideoTest();

	QPushButton *btOk;
	QPushButton *btCancel;

	void loadSettings();
	void storeSettings();

	void fillDevicesComboBox(QComboBox *cb, MediaDevice *dev, enum MediaDeviceStreamDirection dir);

private slots:
	void OK();
	void Cancel();
	void toggleIncomingConnections(bool checked);
	void toggleMultipleLogins(bool checked);
	void fillVideoDevices();
	// Device names are driver specific, so all three lists have to be filled
	// again when the driver changes. Only ever connected on Linux.
	void audioDriverChanged(int index);
	void fillAudioCaptureDevices();
	void fillAudioPlaybackDevices();
	void fillAudioRingDevices();

	void toggleRingTest();
	void ringTestFinished();
	void ringTestError(QString message);

	void toggleAudioTest();
	void audioTestPacket(QByteArray data);
	void audioTestRecordingFinished();
	void audioTestFeedPacket();
	void audioTestPlaybackFinished();
	void audioTestError(QString message);
	void audioTestPath(QString description);

	void toggleVideoTest();
	void videoTestCaptureStarted(QString codec, int width, int height);
	void videoTestPath(QString description);
	void videoTestFragment(QByteArray data, bool is_last_fragment);
	void videoTestFrame(QImage frame);
#ifdef HAVE_VAAPI
	void videoTestHwFrame(AVFramePtr frame);
	void videoTestRenderFailed(QString message);
#endif
	void videoTestError(QString message);

};

#endif // SETTINGSDIALOG_H