blob: fedf146ae80ee418b09df23ebfaa6d8dede4799f [file] [log] [blame]
Stepan Salenikovichb7e6a732015-05-04 17:13:22 -04001/*
2 * Copyright (C) 2015 Savoir-Faire Linux Inc.
3 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30
31#include "accountadvancedtab.h"
32
33#include <gtk/gtk.h>
34#include <account.h>
35
36struct _AccountAdvancedTab
37{
38 GtkBox parent;
39};
40
41struct _AccountAdvancedTabClass
42{
43 GtkBoxClass parent_class;
44};
45
46typedef struct _AccountAdvancedTabPrivate AccountAdvancedTabPrivate;
47
48struct _AccountAdvancedTabPrivate
49{
50 Account *account;
51 GtkWidget *vbox_main;
52 GtkWidget *frame_registration;
53 GtkWidget *adjustment_registration_timeout;
54 GtkWidget *frame_network_interface;
55 GtkWidget *box_network_interface;
56 GtkWidget *checkbutton_use_random_port;
57 GtkWidget *box_local_port;
58 GtkWidget *adjustment_local_port;
59 GtkWidget *radiobutton_same_as_local;
60 GtkWidget *radiobutton_set_published;
61 GtkWidget *box_published_address_port;
62 GtkWidget *entry_published_address;
63 GtkWidget *spinbutton_published_port;
64 GtkWidget *adjustment_published_port;
65 GtkWidget *checkbutton_use_stun;
66 GtkWidget *entry_stun_server;
67 GtkWidget *checkbutton_use_turn;
68 GtkWidget *entry_turn_server;
69 GtkWidget *adjustment_audio_port_min;
70 GtkWidget *adjustment_audio_port_max;
71 GtkWidget *adjustment_video_port_min;
72 GtkWidget *adjustment_video_port_max;
73
74 QMetaObject::Connection account_updated;
75};
76
77G_DEFINE_TYPE_WITH_PRIVATE(AccountAdvancedTab, account_advanced_tab, GTK_TYPE_BOX);
78
79#define ACCOUNT_ADVANCED_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_ADVANCED_TAB_TYPE, AccountAdvancedTabPrivate))
80
81static void
82account_advanced_tab_dispose(GObject *object)
83{
84 AccountAdvancedTab *view = ACCOUNT_ADVANCED_TAB(object);
85 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(view);
86
87 QObject::disconnect(priv->account_updated);
88
89 G_OBJECT_CLASS(account_advanced_tab_parent_class)->dispose(object);
90}
91
92static void
93account_advanced_tab_init(AccountAdvancedTab *view)
94{
95 gtk_widget_init_template(GTK_WIDGET(view));
96}
97
98static void
99account_advanced_tab_class_init(AccountAdvancedTabClass *klass)
100{
101 G_OBJECT_CLASS(klass)->dispose = account_advanced_tab_dispose;
102
103 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
104 "/cx/ring/RingGnome/accountadvancedtab.ui");
105
106 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, vbox_main);
107 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, frame_registration);
108 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_registration_timeout);
109 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, frame_network_interface);
110 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, box_network_interface);
111 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, checkbutton_use_random_port);
112 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, box_local_port);
113 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_local_port);
114 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, radiobutton_same_as_local);
115 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, radiobutton_set_published);
116 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, box_published_address_port);
117 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, entry_published_address);
118 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, spinbutton_published_port);
119 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_published_port);
120 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, checkbutton_use_stun);
121 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, entry_stun_server);
122 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, checkbutton_use_turn);
123 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, entry_turn_server);
124 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_audio_port_min);
125 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_audio_port_max);
126 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_video_port_min);
127 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAdvancedTab, adjustment_video_port_max);
128}
129
130static void
131registration_expire_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
132{
133 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
134 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
135
136 int timeout = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
137 priv->account->setRegistrationExpire(timeout);
138}
139
140static void
141local_port_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
142{
143 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
144 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
145
146 unsigned short int local_port = (unsigned short int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
147
148 if (priv->account->protocol() != Account::Protocol::RING) {
149 priv->account->setLocalPort(local_port);
150 } else {
151 priv->account->setBootstrapPort(local_port);
152 }
153}
154
155static void
156same_as_local_toggled(GtkToggleButton *toggle_button, AccountAdvancedTab *self)
157{
158 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
159 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
160
161 gboolean published_same_as_local = gtk_toggle_button_get_active(toggle_button);
162
163 priv->account->setPublishedSameAsLocal(published_same_as_local);
164
165 /* disactivate the published address and port fields if same as local is true */
166 gtk_widget_set_sensitive(priv->box_published_address_port, !published_same_as_local);
167}
168
169static void
170published_address_changed(GtkEntry *entry, AccountAdvancedTab *self)
171{
172 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
173 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
174
175 priv->account->setPublishedAddress(gtk_entry_get_text(entry));
176}
177
178static void
179published_port_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
180{
181 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
182 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
183
184 unsigned short int published_port = (unsigned short int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
185 priv->account->setPublishedPort(published_port);
186}
187
188static void
189stun_enabled_toggled(GtkToggleButton *toggle_button, AccountAdvancedTab *self)
190{
191 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
192 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
193
194 gboolean use_stun = gtk_toggle_button_get_active(toggle_button);
195
196 priv->account->setSipStunEnabled(use_stun);
197
198 /* disactivate the stun server entry if stun is disabled */
199 gtk_widget_set_sensitive(priv->entry_stun_server, use_stun);
200}
201
202static void
203stun_server_changed(GtkEntry *entry, AccountAdvancedTab *self)
204{
205 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
206 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
207
208 priv->account->setSipStunServer(gtk_entry_get_text(entry));
209}
210
211static void
212turn_enabled_toggled(GtkToggleButton *toggle_button, AccountAdvancedTab *self)
213{
214 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
215 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
216
217 gboolean use_turn = gtk_toggle_button_get_active(toggle_button);
218
219 priv->account->setTurnEnabled(use_turn);
220
221 /* disactivate the turn server entry if turn is disabled */
222 gtk_widget_set_sensitive(priv->entry_turn_server, use_turn);
223}
224
225static void
226turn_server_changed(GtkEntry *entry, AccountAdvancedTab *self)
227{
228 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
229 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
230
231 priv->account->setTurnServer(gtk_entry_get_text(entry));
232}
233
234static void
235audio_port_min_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
236{
237 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
238 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
239
240 int port = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
241 priv->account->setAudioPortMin(port);
242}
243
244static void
245audio_port_max_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
246{
247 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
248 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
249
250 int port = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
251 priv->account->setAudioPortMax(port);
252}
253
254static void
255video_port_min_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
256{
257 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
258 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
259
260 int port = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
261 priv->account->setVideoPortMin(port);
262}
263
264static void
265video_port_max_changed(GtkAdjustment *adjustment, AccountAdvancedTab *self)
266{
267 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
268 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
269
270 int port = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
271 priv->account->setVideoPortMax(port);
272}
273
274static void
275build_tab_view(AccountAdvancedTab *self)
276{
277 g_return_if_fail(IS_ACCOUNT_ADVANCED_TAB(self));
278 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(self);
279
280 /* check if its ip2ip account */
281 const QByteArray& alias = priv->account->alias().toUtf8();
282
283 /* only show registration timeout for SIP account */
284 if ( (priv->account->protocol() != Account::Protocol::SIP)
285 || (strcmp(alias.constData(), "IP2IP") == 0) ) {
286 gtk_container_remove(GTK_CONTAINER(priv->vbox_main), priv->frame_registration);
287 priv->frame_registration = NULL;
288 } else {
289 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_registration_timeout),
290 priv->account->registrationExpire());
291 g_signal_connect(priv->adjustment_registration_timeout,
292 "value-changed", G_CALLBACK(registration_expire_changed), self);
293 }
294
295 /* local port */
296 if (priv->account->protocol() != Account::Protocol::RING) {
297 gtk_container_remove(GTK_CONTAINER(priv->box_network_interface), priv->checkbutton_use_random_port);
298 priv->checkbutton_use_random_port = NULL;
299 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_local_port),
300 priv->account->localPort());
301 g_signal_connect(priv->adjustment_local_port,
302 "value-changed", G_CALLBACK(local_port_changed), self);
303 } else {
304 /* TODO: when this option is added, for now just don't set it
305 * gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_local_port),
306 * priv->account->bootstrapPort());
307 */
308 gtk_container_remove(GTK_CONTAINER(priv->vbox_main), priv->frame_network_interface);
309 priv->frame_network_interface = NULL;
310 }
311
312 /* published address/port same as local */
313 if (priv->account->isPublishedSameAsLocal()) {
314 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_same_as_local), TRUE);
315
316 /* disactivate the published address and port fields if same as local is true */
317 gtk_widget_set_sensitive(priv->box_published_address_port, FALSE);
318 } else {
319 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_set_published), TRUE);
320 }
321
322 g_signal_connect(priv->radiobutton_same_as_local,
323 "toggled", G_CALLBACK(same_as_local_toggled), self);
324
325 /* published address and port */
326 gtk_entry_set_text(GTK_ENTRY(priv->entry_published_address),
327 priv->account->publishedAddress().toUtf8().constData());
328 g_signal_connect(priv->entry_published_address,
329 "changed", G_CALLBACK(published_address_changed), self);
330
331 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_published_port),
332 priv->account->publishedPort());
333 g_signal_connect(priv->adjustment_published_port,
334 "value-changed", G_CALLBACK(published_port_changed), self);
335
336 /* STUN */
337 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_stun),
338 priv->account->isSipStunEnabled());
339 gtk_entry_set_text(GTK_ENTRY(priv->entry_stun_server),
340 priv->account->sipStunServer().toUtf8().constData());
341 gtk_widget_set_sensitive(priv->entry_stun_server,
342 priv->account->isSipStunEnabled());
343 g_signal_connect(priv->checkbutton_use_stun,
344 "toggled", G_CALLBACK(stun_enabled_toggled), self);
345 g_signal_connect(priv->entry_stun_server,
346 "changed", G_CALLBACK(stun_server_changed), self);
347
348 /* TURN */
349 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_turn),
350 priv->account->isTurnEnabled());
351 gtk_entry_set_text(GTK_ENTRY(priv->entry_turn_server),
352 priv->account->turnServer().toUtf8().constData());
353 gtk_widget_set_sensitive(priv->entry_turn_server,
354 priv->account->isTurnEnabled());
355 g_signal_connect(priv->checkbutton_use_turn,
356 "toggled", G_CALLBACK(turn_enabled_toggled), self);
357 g_signal_connect(priv->entry_turn_server,
358 "changed", G_CALLBACK(turn_server_changed), self);
359
360 /* audio/video rtp port range */
361 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_audio_port_min),
362 priv->account->audioPortMin());
363 g_signal_connect(priv->adjustment_audio_port_min,
364 "value-changed", G_CALLBACK(audio_port_min_changed), self);
365 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_audio_port_max),
366 priv->account->audioPortMax());
367 g_signal_connect(priv->adjustment_audio_port_min,
368 "value-changed", G_CALLBACK(audio_port_max_changed), self);
369 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_video_port_min),
370 priv->account->videoPortMin());
371 g_signal_connect(priv->adjustment_audio_port_min,
372 "value-changed", G_CALLBACK(video_port_min_changed), self);
373 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_video_port_max),
374 priv->account->videoPortMax());
375 g_signal_connect(priv->adjustment_video_port_max,
376 "value-changed", G_CALLBACK(video_port_max_changed), self);
377
378 /* update account UI if model is updated */
379 priv->account_updated = QObject::connect(
380 priv->account,
381 &Account::changed,
382 [=] () {
383 /* only show registration timeout for SIP account */
384 if ( priv->frame_registration ) {
385 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_registration_timeout),
386 priv->account->registrationExpire());
387 }
388
389 /* local port */
390 if (priv->account->protocol() != Account::Protocol::RING) {
391 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_local_port),
392 priv->account->localPort());
393 }
394
395 /* published address/port same as local */
396 if (priv->account->isPublishedSameAsLocal()) {
397 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_same_as_local), TRUE);
398 } else {
399 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_set_published), TRUE);
400 }
401
402 /* published address and port */
403 gtk_entry_set_text(GTK_ENTRY(priv->entry_published_address),
404 priv->account->publishedAddress().toUtf8().constData());
405 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_published_port),
406 priv->account->publishedPort());
407
408 /* STUN */
409 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_stun),
410 priv->account->isSipStunEnabled());
411 gtk_entry_set_text(GTK_ENTRY(priv->entry_stun_server),
412 priv->account->sipStunServer().toUtf8().constData());
413
414 /* TURN */
415 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_turn),
416 priv->account->isTurnEnabled());
417 gtk_entry_set_text(GTK_ENTRY(priv->entry_turn_server),
418 priv->account->turnServer().toUtf8().constData());
419
420 /* audio/video rtp port range */
421 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_audio_port_min),
422 priv->account->audioPortMin());
423 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_audio_port_max),
424 priv->account->audioPortMax());
425 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_video_port_min),
426 priv->account->videoPortMin());
427 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_video_port_max),
428 priv->account->videoPortMax());
429 }
430 );
431}
432
433GtkWidget *
434account_advanced_tab_new(Account *account)
435{
436 g_return_val_if_fail(account != NULL, NULL);
437
438 gpointer view = g_object_new(ACCOUNT_ADVANCED_TAB_TYPE, NULL);
439
440 AccountAdvancedTabPrivate *priv = ACCOUNT_ADVANCED_TAB_GET_PRIVATE(view);
441 priv->account = account;
442
443 build_tab_view(ACCOUNT_ADVANCED_TAB(view));
444
445 return (GtkWidget *)view;
446}