1 #include "settings.h"
2
3 #include "debug.h"
4 #include "flist.h"
5 #include "groups.h"
6 #include "tox.h"
7
8 // TODO do we want to include the UI headers here?
9 // Or would it be better to supply a callback after settings are loaded?
10 #include "ui/edit.h"
11 #include "ui/switch.h"
12 #include "ui/dropdown.h"
13
14 #include "layout/settings.h"
15
16 #include "native/filesys.h"
17 #include "native/keyboard.h"
18
19 #include "main.h" // UTOX_VERSION_NUMBER, MAIN_HEIGHT, MAIN_WIDTH, all save things..
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <minIni.h>
24
25 #define MATCH(x, y) (strcasecmp(x, y) == 0)
26 #define BOOL_TO_STR(b) b ? "true" : "false"
27 #define STR_TO_BOOL(s) (strcasecmp(s, "true") == 0)
28 #define NAMEOF(s) strchr((const char *)(#s), '>') == NULL ? #s : (strchr((const char *)(#s), '>') + 1)
29
30 uint16_t loaded_audio_out_device = 0;
31 uint16_t loaded_audio_in_device = 0;
32
33 static const char *config_file_name = "utox_save.ini";
34 static const char *config_file_name_old = "utox_save";
35
36 static const uint16_t proxy_address_size = 256; // Magic number inside Toxcore.
37
38 /**
39 * Config section names.
40 */
41 typedef enum {
42 GENERAL_SECTION,
43 INTERFACE_SECTION,
44 AV_SECTION,
45 NOTIFICATIONS_SECTION,
46 ADVANCED_SECTION,
47 UNKNOWN_SECTION
48 } CONFIG_SECTION;
49
50 static const char *config_sections[UNKNOWN_SECTION + 1] = {
51 "general",
52 "interface",
53 "av",
54 "notifications",
55 "advanced",
56 NULL
57 };
58
59 SETTINGS settings = {
60 // .last_version // included here to match the full struct
61 .curr_version = UTOX_VERSION_NUMBER,
62 .next_version = UTOX_VERSION_NUMBER,
63
64 .show_splash = false,
65
66 // Low level settings (network, profile, portable-mode)
67 .enable_udp = true,
68 .enable_ipv6 = true,
69
70 .use_proxy = false,
71 .force_proxy = false,
72 .proxy_port = 0,
73
74 // Tox level settings
75 .block_friend_requests = false,
76 .save_encryption = true,
77
78 // .portable_mode // included here to match the full struct
79
80 // User interface settings
81 .language = LANG_EN,
82 .audiofilter_enabled = true,
83 .push_to_talk = false,
84 .audio_preview = false,
85 .video_preview = false,
86 .send_typing_status = false,
87 // .inline_video // included here to match the full struct
88 .use_long_time_msg = true,
89 .accept_inline_images = true,
90
91 // UX Settings
92 .logging_enabled = true,
93 .close_to_tray = false,
94 .start_in_tray = false,
95 .start_with_system = false,
96 .use_mini_flist = false,
97 .magic_flist_enabled = false,
98
99 .video_fps = DEFAULT_FPS,
100
101 // Notifications / Alerts
102 .ringtone_enabled = true,
103 .status_notifications = true,
104 .group_notifications = GNOTIFY_ALWAYS,
105
106 .verbose = LOG_LVL_ERROR,
107 .debug_file = NULL,
108
109 .theme = UINT32_MAX,
110 // OS interface settings
111 .window_x = 0,
112 .window_y = 0,
113 .window_height = MAIN_HEIGHT,
114 .window_width = MAIN_WIDTH,
115 .window_baseline = 0,
116
117 .window_maximized = 0,
118 };
119
write_config_value_int(const char * filename,const char * section,const char * key,const long value)120 static void write_config_value_int(const char *filename, const char *section, const char *key, const long value) {
121 if (ini_putl(section, key, value, filename) != 1) {
122 LOG_ERR("Settings", "Unable to save config value: %lu.", value);
123 }
124 }
125
write_config_value_str(const char * filename,const char * section,const char * key,const char * value)126 static void write_config_value_str(const char *filename, const char *section, const char *key, const char *value) {
127 if (ini_puts(section, key, value, filename) != 1) {
128 LOG_ERR("Settings", "Unable to save config value: %s.", value);
129 }
130 }
131
write_config_value_bool(const char * filename,const char * section,const char * key,const bool value)132 static void write_config_value_bool(const char *filename, const char *section, const char *key, const bool value) {
133 if (ini_puts(section, key, BOOL_TO_STR(value), filename) != 1) {
134 LOG_ERR("Settings", "Unable to save config value: %s.", value);
135 }
136 }
137
get_section(const char * section)138 static CONFIG_SECTION get_section(const char* section) {
139 if (MATCH(config_sections[GENERAL_SECTION], section)) {
140 return GENERAL_SECTION;
141 } else if (MATCH(config_sections[INTERFACE_SECTION], section)) {
142 return INTERFACE_SECTION;
143 } else if (MATCH(config_sections[AV_SECTION], section)) {
144 return AV_SECTION;
145 } else if (MATCH(config_sections[NOTIFICATIONS_SECTION], section)) {
146 return NOTIFICATIONS_SECTION;
147 } else if (MATCH(config_sections[ADVANCED_SECTION], section)) {
148 return ADVANCED_SECTION;
149 } else {
150 return UNKNOWN_SECTION;
151 }
152 }
153
parse_general_section(UTOX_SAVE * config,const char * key,const char * value)154 static void parse_general_section(UTOX_SAVE *config, const char* key, const char* value) {
155 if (MATCH(NAMEOF(config->save_version), key)) {
156 config->save_version = atoi(value);
157 } else if (MATCH(NAMEOF(config->utox_last_version), key)) {
158 config->utox_last_version = atoi(value);
159 } else if (MATCH(NAMEOF(config->send_version), key)) {
160 config->send_version = STR_TO_BOOL(value);
161 } else if (MATCH(NAMEOF(config->update_to_develop), key)) {
162 config->update_to_develop = STR_TO_BOOL(value);
163 }
164 }
165
parse_interface_section(UTOX_SAVE * config,const char * key,const char * value)166 static void parse_interface_section(UTOX_SAVE *config, const char* key, const char* value) {
167 if (MATCH(NAMEOF(config->language), key)) {
168 config->language = atoi(value);
169 } else if (MATCH(NAMEOF(config->window_x), key)) {
170 config->window_x = atoi(value);
171 } else if (MATCH(NAMEOF(config->window_y), key)) {
172 config->window_y = atoi(value);
173 } else if (MATCH(NAMEOF(config->window_width), key)) {
174 config->window_width = atoi(value);
175 } else if (MATCH(NAMEOF(config->window_height), key)) {
176 config->window_height = atoi(value);
177 } else if (MATCH(NAMEOF(config->theme), key)) {
178 config->theme = atoi(value);
179 } else if (MATCH(NAMEOF(config->scale), key)) {
180 config->scale = atoi(value);
181 } else if (MATCH(NAMEOF(config->logging_enabled), key)) {
182 config->logging_enabled = STR_TO_BOOL(value);
183 } else if (MATCH(NAMEOF(config->close_to_tray), key)) {
184 config->close_to_tray = STR_TO_BOOL(value);
185 } else if (MATCH(NAMEOF(config->start_in_tray), key)) {
186 config->start_in_tray = STR_TO_BOOL(value);
187 } else if (MATCH(NAMEOF(config->auto_startup), key)) {
188 config->auto_startup = STR_TO_BOOL(value);
189 } else if (MATCH(NAMEOF(config->use_mini_flist), key)) {
190 config->use_mini_flist = STR_TO_BOOL(value);
191 } else if (MATCH(NAMEOF(config->filter), key)) {
192 config->filter = STR_TO_BOOL(value);
193 } else if (MATCH(NAMEOF(config->magic_flist_enabled), key)) {
194 config->magic_flist_enabled = STR_TO_BOOL(value);
195 } else if (MATCH(NAMEOF(config->use_long_time_msg), key)) {
196 config->use_long_time_msg = STR_TO_BOOL(value);
197 }
198 }
199
parse_av_section(UTOX_SAVE * config,const char * key,const char * value)200 static void parse_av_section(UTOX_SAVE *config, const char* key, const char* value) {
201 if (MATCH(NAMEOF(config->push_to_talk), key)) {
202 config->push_to_talk = STR_TO_BOOL(value);
203 } else if (MATCH(NAMEOF(config->audio_filtering_enabled), key)) {
204 config->audio_filtering_enabled = STR_TO_BOOL(value);
205 } else if (MATCH(NAMEOF(config->audio_device_in), key)) {
206 config->audio_device_in = atoi(value);
207 } else if (MATCH(NAMEOF(config->audio_device_out), key)) {
208 config->audio_device_out = atoi(value);
209 } else if (MATCH(NAMEOF(config->video_fps), key)) {
210 char *temp;
211 uint16_t value_fps = strtol((char *)value, &temp, 0);
212
213 if (*temp == '\0' && value_fps >= 1 && value_fps <= UINT8_MAX) {
214 settings.video_fps = value_fps;
215 return;
216 }
217
218 LOG_WARN("Settings", "Fps value (%s) is invalid. It must be integer in range of [1,%u].",
219 value, UINT8_MAX);
220 }
221 }
222
parse_notifications_section(UTOX_SAVE * config,const char * key,const char * value)223 static void parse_notifications_section(UTOX_SAVE *config, const char* key, const char* value) {
224 if (MATCH(NAMEOF(config->audible_notifications_enabled), key)) {
225 config->audible_notifications_enabled = STR_TO_BOOL(value);
226 } else if (MATCH(NAMEOF(config->status_notifications), key)) {
227 config->status_notifications = STR_TO_BOOL(value);
228 } else if (MATCH(NAMEOF(config->no_typing_notifications), key)) {
229 config->no_typing_notifications = STR_TO_BOOL(value);
230 } else if (MATCH(NAMEOF(config->group_notifications), key)) {
231 config->group_notifications = atoi(value);
232 }
233 }
234
parse_advanced_section(UTOX_SAVE * config,const char * key,const char * value)235 static void parse_advanced_section(UTOX_SAVE *config, const char* key, const char* value) {
236 if (MATCH(NAMEOF(config->enableipv6), key)) {
237 config->enableipv6 = STR_TO_BOOL(value);
238 } else if (MATCH(NAMEOF(config->disableudp), key)) {
239 config->disableudp = STR_TO_BOOL(value);
240 } else if (MATCH(NAMEOF(config->proxyenable), key)) {
241 config->proxyenable = STR_TO_BOOL(value);
242 } else if (MATCH(NAMEOF(config->proxy_port), key)) {
243 config->proxy_port = atoi(value);
244 } else if (MATCH(NAMEOF(config->proxy_ip), key)) {
245 strcpy((char *)config->proxy_ip, value);
246 } else if (MATCH(NAMEOF(config->force_proxy), key)) {
247 config->force_proxy = STR_TO_BOOL(value);
248 } else if (MATCH(NAMEOF(config->auto_update), key)) {
249 config->auto_update = STR_TO_BOOL(value);
250 }
251 }
252
config_parser(const char * section,const char * key,const char * value,void * config_v)253 static int config_parser(const char* section, const char* key, const char* value, void* config_v) {
254 UTOX_SAVE *config = (UTOX_SAVE*) config_v;
255
256 switch(get_section(section)) {
257 case GENERAL_SECTION: {
258 parse_general_section(config, key, value);
259 break;
260 }
261 case INTERFACE_SECTION: {
262 parse_interface_section(config, key, value);
263 break;
264 }
265 case AV_SECTION: {
266 parse_av_section(config, key, value);
267 break;
268 }
269 case NOTIFICATIONS_SECTION: {
270 parse_notifications_section(config, key, value);
271 break;
272 }
273 case ADVANCED_SECTION: {
274 parse_advanced_section(config, key, value);
275 break;
276 }
277 case UNKNOWN_SECTION: {
278 LOG_NOTE("Settings", "Unknown section in config file: %s", section);
279 break;
280 }
281 }
282
283 return 1;
284 }
285
utox_load_config(void)286 static UTOX_SAVE *utox_load_config(void) {
287 UTOX_SAVE *save = calloc(1, sizeof(UTOX_SAVE) + proxy_address_size + 1);
288 if (!save) {
289 LOG_ERR("Settings", "Unable to calloc for UTOX_SAVE.");
290 return NULL;
291 }
292
293 char *config_path = utox_get_filepath(config_file_name);
294
295 if (!config_path) {
296 LOG_ERR("Settings", "Unable to get %s path.", config_file_name);
297 free(save);
298 return NULL;
299 }
300
301 if (!ini_browse(config_parser, save, config_path)) {
302 LOG_ERR("Settings", "Unable to parse %s.", config_file_name);
303 free(config_path);
304 free(save);
305 return NULL;
306 }
307
308 free(config_path);
309
310 return save;
311 }
312
utox_save_config(UTOX_SAVE * config)313 static bool utox_save_config(UTOX_SAVE *config) {
314 char *config_path = utox_get_filepath(config_file_name);
315
316 if (!config_path) {
317 LOG_ERR("Settings", "Unable to get %s path.", config_file_name);
318 return false;
319 }
320
321 // general
322 write_config_value_int(config_path, config_sections[GENERAL_SECTION], NAMEOF(config->save_version), config->save_version);
323 write_config_value_int(config_path, config_sections[GENERAL_SECTION], NAMEOF(config->utox_last_version), config->utox_last_version);
324 write_config_value_bool(config_path, config_sections[GENERAL_SECTION], NAMEOF(config->send_version), config->send_version);
325 write_config_value_bool(config_path, config_sections[GENERAL_SECTION], NAMEOF(config->update_to_develop), config->update_to_develop);
326
327 // interface
328 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->language), config->language);
329 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->window_x), config->window_x);
330 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->window_y), config->window_y);
331 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->window_width), config->window_width);
332 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->window_height), config->window_height);
333 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->theme), config->theme);
334 write_config_value_int(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->scale), config->scale);
335 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->logging_enabled), config->logging_enabled);
336 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->close_to_tray), config->close_to_tray);
337 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->start_in_tray), config->start_in_tray);
338 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->auto_startup), config->auto_startup);
339 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->use_mini_flist), config->use_mini_flist);
340 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->filter), config->filter);
341 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->magic_flist_enabled), config->magic_flist_enabled);
342 write_config_value_bool(config_path, config_sections[INTERFACE_SECTION], NAMEOF(config->use_long_time_msg), config->use_long_time_msg);
343
344 // av
345 write_config_value_bool(config_path, config_sections[AV_SECTION], NAMEOF(config->push_to_talk), config->push_to_talk);
346 write_config_value_bool(config_path, config_sections[AV_SECTION], NAMEOF(config->audio_filtering_enabled), config->audio_filtering_enabled);
347 write_config_value_int(config_path, config_sections[AV_SECTION], NAMEOF(config->audio_device_in), config->audio_device_in);
348 write_config_value_int(config_path, config_sections[AV_SECTION], NAMEOF(config->audio_device_out), config->audio_device_out);
349 write_config_value_int(config_path, config_sections[AV_SECTION], NAMEOF(config->video_fps), config->video_fps);
350 // TODO: video_input_device
351
352 // notifications
353 write_config_value_bool(config_path, config_sections[NOTIFICATIONS_SECTION], NAMEOF(config->audible_notifications_enabled), config->audible_notifications_enabled);
354 write_config_value_bool(config_path, config_sections[NOTIFICATIONS_SECTION], NAMEOF(config->status_notifications), config->status_notifications);
355 write_config_value_bool(config_path, config_sections[NOTIFICATIONS_SECTION], NAMEOF(config->no_typing_notifications), config->no_typing_notifications);
356 write_config_value_int(config_path, config_sections[NOTIFICATIONS_SECTION], NAMEOF(config->group_notifications), config->group_notifications);
357
358 // advanced
359 write_config_value_bool(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->enableipv6), config->enableipv6);
360 write_config_value_bool(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->disableudp), config->disableudp);
361 write_config_value_bool(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->proxyenable), config->proxyenable);
362 write_config_value_int(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->proxy_port), config->proxy_port);
363 write_config_value_str(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->proxy_ip), (const char *)config->proxy_ip);
364 write_config_value_bool(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->force_proxy), config->force_proxy);
365 write_config_value_bool(config_path, config_sections[ADVANCED_SECTION], NAMEOF(config->auto_update), config->auto_update);
366 // TODO: block_friend_requests
367
368 free(config_path);
369
370 return true;
371 }
372
init_default_settings(void)373 static UTOX_SAVE *init_default_settings(void) {
374 UTOX_SAVE *save = calloc(1, sizeof(UTOX_SAVE));
375 if (!save) {
376 LOG_FATAL_ERR(EXIT_MALLOC, "Settings", "Unable to malloc for default settings.");
377 }
378
379 save->enableipv6 = true;
380 save->disableudp = false;
381 save->proxyenable = false;
382 save->force_proxy = false;
383
384 save->audio_filtering_enabled = true;
385 save->audible_notifications_enabled = true;
386
387 return save;
388 }
389
390 // TODO refactor to match same order in main.h
config_load(void)391 UTOX_SAVE *config_load(void) {
392 UTOX_SAVE *save = utox_load_config();
393
394 // TODO: Remove this in ~0.18.0 release
395 if (!save) {
396 LOG_NOTE("Settings", "Unable to load uTox settings from %s. Trying old %s.", config_file_name, config_file_name_old);
397 save = utox_data_load_utox();
398 }
399
400 if (!save) {
401 LOG_ERR("Settings", "Unable to load uTox settings. Use defaults.");
402 save = init_default_settings();
403 }
404
405 if (save->scale > 30) {
406 save->scale = 30;
407 } else if (save->scale < 5) {
408 save->scale = 10;
409 }
410
411 if (save->window_width < MAIN_WIDTH) {
412 save->window_width = MAIN_WIDTH;
413 }
414 if (save->window_height < MAIN_HEIGHT) {
415 save->window_height = MAIN_HEIGHT;
416 }
417
418 /* UX Settings */
419
420 dropdown_language.selected = dropdown_language.over = settings.language = save->language;
421
422 dropdown_dpi.selected = dropdown_dpi.over = save->scale - 5;
423
424 switch_save_chat_history.switch_on = save->logging_enabled;
425 switch_close_to_tray.switch_on = save->close_to_tray;
426 switch_start_in_tray.switch_on = save->start_in_tray;
427 switch_mini_contacts.switch_on = save->use_mini_flist;
428 switch_magic_sidebar.switch_on = save->magic_flist_enabled;
429
430 switch_ipv6.switch_on = save->enableipv6;
431 switch_udp.switch_on = !save->disableudp;
432 switch_udp.panel.disabled = save->force_proxy;
433 switch_proxy.switch_on = save->proxyenable;
434 switch_proxy_force.switch_on = save->force_proxy;
435 switch_proxy_force.panel.disabled = !save->proxyenable;
436
437 switch_auto_startup.switch_on = save->auto_startup;
438
439 settings.group_notifications = dropdown_global_group_notifications.selected =
440 dropdown_global_group_notifications.over = save->group_notifications;
441
442 switch_audible_notifications.switch_on = save->audible_notifications_enabled;
443 switch_audio_filtering.switch_on = save->audio_filtering_enabled;
444 switch_push_to_talk.switch_on = save->push_to_talk;
445 switch_status_notifications.switch_on = save->status_notifications;
446
447 dropdown_theme.selected = dropdown_theme.over = save->theme;
448
449 switch_typing_notes.switch_on = !save->no_typing_notifications;
450
451 flist_set_filter(save->filter); /* roster list filtering */
452
453 /* Network settings */
454 settings.enable_ipv6 = save->enableipv6;
455 settings.enable_udp = !save->disableudp;
456 settings.use_proxy = !!save->proxyenable;
457 settings.proxy_port = save->proxy_port;
458 settings.force_proxy = save->force_proxy;
459
460 if (strlen((char *)save->proxy_ip) <= proxy_address_size){
461 strcpy((char *)proxy_address, (char *)save->proxy_ip);
462 }
463
464 edit_proxy_ip.length = strlen((char *)save->proxy_ip);
465
466 strcpy((char *)edit_proxy_ip.data, (char *)save->proxy_ip);
467
468 if (save->proxy_port) {
469 snprintf((char *)edit_proxy_port.data, edit_proxy_port.data_size,
470 "%u", save->proxy_port);
471 edit_proxy_port.length = strnlen((char *)edit_proxy_port.data,
472 edit_proxy_port.data_size - 1);
473 }
474
475 /* UX settings */
476 settings.logging_enabled = save->logging_enabled;
477 settings.close_to_tray = save->close_to_tray;
478 settings.start_in_tray = save->start_in_tray;
479 settings.start_with_system = save->auto_startup;
480 settings.use_mini_flist = save->use_mini_flist;
481 settings.magic_flist_enabled = save->magic_flist_enabled;
482 settings.use_long_time_msg = save->use_long_time_msg;
483
484 settings.ringtone_enabled = save->audible_notifications_enabled;
485 settings.audiofilter_enabled = save->audio_filtering_enabled;
486
487 settings.send_typing_status = !save->no_typing_notifications;
488 settings.status_notifications = save->status_notifications;
489
490 settings.window_x = save->window_x;
491 settings.window_y = save->window_y;
492 settings.window_width = save->window_width;
493 settings.window_height = save->window_height;
494
495 settings.last_version = save->utox_last_version;
496
497 loaded_audio_out_device = save->audio_device_out;
498 loaded_audio_in_device = save->audio_device_in;
499
500 settings.video_fps = save->video_fps != 0 ? save->video_fps : DEFAULT_FPS;
501
502 snprintf((char *)edit_video_fps.data, edit_video_fps.data_size,
503 "%u", settings.video_fps);
504 edit_video_fps.length = strnlen((char *)edit_video_fps.data,
505 edit_video_fps.data_size - 1);
506
507 // TODO: Don't clobber (and start saving) commandline flags.
508
509 // Allow users to override theme on the cmdline.
510 if (settings.theme == UINT32_MAX) {
511 settings.theme = save->theme;
512 }
513
514 ui_set_scale(save->scale);
515
516 if (save->push_to_talk) {
517 init_ptt();
518 }
519
520 return save;
521 }
522
523 // TODO refactor to match order in main.h
config_save(UTOX_SAVE * save_in)524 void config_save(UTOX_SAVE *save_in) {
525 UTOX_SAVE *save = calloc(1, sizeof(UTOX_SAVE) + proxy_address_size);
526 if (!save) {
527 LOG_ERR("Settings", "Could not allocate memory to save settings");
528 return;
529 }
530
531 /* Copy the data from the in data to protect the calloc */
532 save->window_x = save_in->window_x;
533 save->window_y = save_in->window_y;
534 save->window_width = save_in->window_width;
535 save->window_height = save_in->window_height;
536
537 save->save_version = UTOX_SAVE_VERSION;
538 save->scale = ui_scale;
539 save->proxyenable = switch_proxy.switch_on;
540 save->audible_notifications_enabled = settings.ringtone_enabled;
541 save->audio_filtering_enabled = settings.audiofilter_enabled;
542 save->push_to_talk = settings.push_to_talk;
543
544 /* UX Settings */
545 save->logging_enabled = settings.logging_enabled;
546 save->close_to_tray = settings.close_to_tray;
547 save->start_in_tray = settings.start_in_tray;
548 save->auto_startup = settings.start_with_system;
549 save->use_mini_flist = settings.use_mini_flist;
550 save->magic_flist_enabled = settings.magic_flist_enabled;
551 save->use_long_time_msg = settings.use_long_time_msg;
552 save->video_fps = settings.video_fps;
553
554 save->disableudp = !settings.enable_udp;
555 save->enableipv6 = settings.enable_ipv6;
556 save->no_typing_notifications = !settings.send_typing_status;
557
558 save->filter = flist_get_filter();
559 save->proxy_port = settings.proxy_port;
560 save->force_proxy = settings.force_proxy;
561
562 save->audio_device_in = dropdown_audio_in.selected;
563 save->audio_device_out = dropdown_audio_out.selected;
564 save->theme = settings.theme;
565
566 save->utox_last_version = settings.curr_version;
567 save->group_notifications = settings.group_notifications;
568 save->status_notifications = settings.status_notifications;
569
570 save->language = settings.language;
571
572 memcpy(save->proxy_ip, proxy_address, proxy_address_size);
573
574 LOG_NOTE("uTox", "Saving uTox settings.");
575
576 if (!utox_save_config(save)) {
577 LOG_ERR("uTox", "Unable to save uTox settings.");
578 }
579
580 free(save);
581 }
582
583 // TODO: Remove this in ~0.18.0 release
utox_data_load_utox(void)584 UTOX_SAVE *utox_data_load_utox(void) {
585 size_t size = 0;
586 FILE *fp = utox_get_file(config_file_name_old, &size, UTOX_FILE_OPTS_READ);
587
588 if (!fp) {
589 LOG_ERR("Settings", "Unable to open %s.", config_file_name_old);
590 return NULL;
591 }
592
593 UTOX_SAVE *save = calloc(1, size + 1);
594 if (!save) {
595 LOG_ERR("Settings", "Unable to malloc for %s.", config_file_name_old);
596 fclose(fp);
597 return NULL;
598 }
599
600 if (fread(save, size, 1, fp) != 1) {
601 LOG_ERR("Settings", "Could not read save file %s", config_file_name_old);
602 fclose(fp);
603 free(save);
604 return NULL;
605 }
606
607 fclose(fp);
608 return save;
609 }
610