1 /*
2 *
3 * Copyright (C) 2012-2018 by C.H. Huang
4 * plushuang.tw@gmail.com
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * ---
21 *
22 * In addition, as a special exception, the copyright holders give
23 * permission to link the code of portions of this program with the
24 * OpenSSL library under certain conditions as described in each
25 * individual source file, and distribute linked combinations
26 * including the two.
27 * You must obey the GNU Lesser General Public License in all respects
28 * for all of the code used other than OpenSSL. If you modify
29 * file(s) with this exception, you may extend this exception to your
30 * version of the file(s), but you are not obligated to do so. If you
31 * do not wish to do so, delete this exception statement from your
32 * version. If you delete this exception statement from all source
33 * files in the program, then also delete it here.
34 *
35 */
36
37 #include <UgStdio.h>
38 #include <UgString.h>
39 #include <UgJsonFile.h>
40 #include <UgetMedia.h>
41 #include <UgtkSetting.h>
42 #include <UgtkNodeView.h>
43
44 #define UGTK_APP_CLIPBOARD_PATTERN "BIN|ZIP|GZ|7Z|XZ|Z|TAR|TGZ|BZ2|" \
45 "LZH|A[0-9]?|RAR|R[0-9][0-9]|ISO|" \
46 "RPM|DEB|EXE|MSI|APK|" \
47 "3GP|AAC|FLAC|M4A|M4P|MP3|OGG|WAV|WMA|" \
48 "MP4|MKV|WEBM|OGV|AVI|MOV|WMV|FLV|F4V|MPG|MPEG|RMVB"
49
50 #define UGTK_ARIA2_PATH "aria2c"
51
52 #define UGTK_ARIA2_ARGS "--enable-rpc=true -D " \
53 "--disable-ipv6 " \
54 "--check-certificate=false"
55
56 #define UGTK_ARIA2_URI "http://localhost:6800/jsonrpc"
57
58 // ----------------------------------------------------------------------------
59 // WindowSetting
60
61 static const UgEntry UgtkWindowSettingEntry[] =
62 {
63 {"Toolbar", offsetof (struct UgtkWindowSetting, toolbar),
64 UG_ENTRY_BOOL, NULL, NULL},
65 {"Statusbar", offsetof (struct UgtkWindowSetting, statusbar),
66 UG_ENTRY_BOOL, NULL, NULL},
67 {"Category", offsetof (struct UgtkWindowSetting, category),
68 UG_ENTRY_BOOL, NULL, NULL},
69 {"Summary", offsetof (struct UgtkWindowSetting, summary),
70 UG_ENTRY_BOOL, NULL, NULL},
71 {"Banner", offsetof (struct UgtkWindowSetting, banner),
72 UG_ENTRY_BOOL, NULL, NULL},
73 {"x", offsetof (struct UgtkWindowSetting, x),
74 UG_ENTRY_INT, NULL, NULL},
75 {"y", offsetof (struct UgtkWindowSetting, y),
76 UG_ENTRY_INT, NULL, NULL},
77 {"width", offsetof (struct UgtkWindowSetting, width),
78 UG_ENTRY_INT, NULL, NULL},
79 {"height", offsetof (struct UgtkWindowSetting, height),
80 UG_ENTRY_INT, NULL, NULL},
81 {"maximized", offsetof (struct UgtkWindowSetting, maximized),
82 UG_ENTRY_BOOL, NULL, NULL},
83 {"NthCategory", offsetof (struct UgtkWindowSetting, nth_category),
84 UG_ENTRY_INT, NULL, NULL},
85 {"NthStatus", offsetof (struct UgtkWindowSetting, nth_state),
86 UG_ENTRY_INT, NULL, NULL},
87 {"PanedPositionH", offsetof (struct UgtkWindowSetting, paned_position_h),
88 UG_ENTRY_INT, NULL, NULL},
89 {"PanedPositionV", offsetof (struct UgtkWindowSetting, paned_position_v),
90 UG_ENTRY_INT, NULL, NULL},
91 {NULL}, // null-terminated
92 };
93
94 // ----------------------------------------------------------------------------
95 // SummarySetting
96
97 static const UgEntry UgtkSummarySettingEntry[] =
98 {
99 {"name", offsetof (struct UgtkSummarySetting, name),
100 UG_ENTRY_BOOL, NULL, NULL},
101 {"folder", offsetof (struct UgtkSummarySetting, folder),
102 UG_ENTRY_BOOL, NULL, NULL},
103 {"category", offsetof (struct UgtkSummarySetting, category),
104 UG_ENTRY_BOOL, NULL, NULL},
105 {"uri", offsetof (struct UgtkSummarySetting, uri),
106 UG_ENTRY_BOOL, NULL, NULL},
107 {"message", offsetof (struct UgtkSummarySetting, message),
108 UG_ENTRY_BOOL, NULL, NULL},
109 {NULL} // null-terminated
110 };
111
112 // ----------------------------------------------------------------------------
113 // DownloadColumnSetting
114
115 static const UgEntry UgtkDownloadColumnWidthEntry[] =
116 {
117 {"state", offsetof (struct UgtkDownloadColumnWidth, state),
118 UG_ENTRY_INT, NULL, NULL},
119 {"name", offsetof (struct UgtkDownloadColumnWidth, name),
120 UG_ENTRY_INT, NULL, NULL},
121 {"complete", offsetof (struct UgtkDownloadColumnWidth, complete),
122 UG_ENTRY_INT, NULL, NULL},
123 {"total", offsetof (struct UgtkDownloadColumnWidth, total),
124 UG_ENTRY_INT, NULL, NULL},
125 {"percent", offsetof (struct UgtkDownloadColumnWidth, percent),
126 UG_ENTRY_INT, NULL, NULL},
127 {"elapsed", offsetof (struct UgtkDownloadColumnWidth, elapsed),
128 UG_ENTRY_INT, NULL, NULL},
129 {"left", offsetof (struct UgtkDownloadColumnWidth, left),
130 UG_ENTRY_INT, NULL, NULL},
131 {"speed", offsetof (struct UgtkDownloadColumnWidth, speed),
132 UG_ENTRY_INT, NULL, NULL},
133 {"UploadSpeed", offsetof (struct UgtkDownloadColumnWidth, upload_speed),
134 UG_ENTRY_INT, NULL, NULL},
135 {"uploaded", offsetof (struct UgtkDownloadColumnWidth, uploaded),
136 UG_ENTRY_INT, NULL, NULL},
137 {"ratio", offsetof (struct UgtkDownloadColumnWidth, ratio),
138 UG_ENTRY_INT, NULL, NULL},
139 {"retry", offsetof (struct UgtkDownloadColumnWidth, retry),
140 UG_ENTRY_INT, NULL, NULL},
141 {"category", offsetof (struct UgtkDownloadColumnWidth, category),
142 UG_ENTRY_INT, NULL, NULL},
143 {"uri", offsetof (struct UgtkDownloadColumnWidth, uri),
144 UG_ENTRY_INT, NULL, NULL},
145 {"AddedOn", offsetof (struct UgtkDownloadColumnWidth, added_on),
146 UG_ENTRY_INT, NULL, NULL},
147 {"CompletedOn", offsetof (struct UgtkDownloadColumnWidth, completed_on),
148 UG_ENTRY_INT, NULL, NULL},
149 {NULL} // null-terminated
150 };
151
152 static const UgEntry UgtkDownloadColumnSettingEntry[] =
153 {
154 {"complete", offsetof (struct UgtkDownloadColumnSetting, complete),
155 UG_ENTRY_BOOL, NULL, NULL},
156 {"total", offsetof (struct UgtkDownloadColumnSetting, total),
157 UG_ENTRY_BOOL, NULL, NULL},
158 {"percent", offsetof (struct UgtkDownloadColumnSetting, percent),
159 UG_ENTRY_BOOL, NULL, NULL},
160 {"elapsed", offsetof (struct UgtkDownloadColumnSetting, elapsed),
161 UG_ENTRY_BOOL, NULL, NULL},
162 {"left", offsetof (struct UgtkDownloadColumnSetting, left),
163 UG_ENTRY_BOOL, NULL, NULL},
164 {"speed", offsetof (struct UgtkDownloadColumnSetting, speed),
165 UG_ENTRY_BOOL, NULL, NULL},
166 {"UploadSpeed", offsetof (struct UgtkDownloadColumnSetting, upload_speed),
167 UG_ENTRY_BOOL, NULL, NULL},
168 {"uploaded", offsetof (struct UgtkDownloadColumnSetting, uploaded),
169 UG_ENTRY_BOOL, NULL, NULL},
170 {"ratio", offsetof (struct UgtkDownloadColumnSetting, ratio),
171 UG_ENTRY_BOOL, NULL, NULL},
172 {"retry", offsetof (struct UgtkDownloadColumnSetting, retry),
173 UG_ENTRY_BOOL, NULL, NULL},
174 {"category", offsetof (struct UgtkDownloadColumnSetting, category),
175 UG_ENTRY_BOOL, NULL, NULL},
176 {"uri", offsetof (struct UgtkDownloadColumnSetting, uri),
177 UG_ENTRY_BOOL, NULL, NULL},
178 {"AddedOn", offsetof (struct UgtkDownloadColumnSetting, added_on),
179 UG_ENTRY_BOOL, NULL, NULL},
180 {"CompletedOn", offsetof (struct UgtkDownloadColumnSetting, completed_on),
181 UG_ENTRY_BOOL, NULL, NULL},
182
183 {"SortType", offsetof (struct UgtkDownloadColumnSetting, sort.type),
184 UG_ENTRY_INT, NULL, NULL},
185 {"SortNth", offsetof (struct UgtkDownloadColumnSetting, sort.nth),
186 UG_ENTRY_INT, NULL, NULL},
187
188 {"Width", offsetof (struct UgtkDownloadColumnSetting, width),
189 UG_ENTRY_OBJECT, (void*) UgtkDownloadColumnWidthEntry, NULL},
190
191 // deprecated
192 {"completed", offsetof (struct UgtkDownloadColumnSetting, complete),
193 UG_ENTRY_BOOL, NULL, NULL},
194
195 {NULL} // null-terminated
196 };
197
198 // ----------------------------------------------------------------------------
199 // UserInterfaceSetting
200
201 static const UgEntry UgtkUserInterfaceSettingEntry[] =
202 {
203 {"ExitConfirmation", offsetof (struct UgtkUserInterfaceSetting, exit_confirmation),
204 UG_ENTRY_BOOL, NULL, NULL},
205 {"DeleteConfirmation", offsetof (struct UgtkUserInterfaceSetting, delete_confirmation),
206 UG_ENTRY_BOOL, NULL, NULL},
207 {"ShowTrayIcon", offsetof (struct UgtkUserInterfaceSetting, show_trayicon),
208 UG_ENTRY_BOOL, NULL, NULL},
209 {"StartInTray", offsetof (struct UgtkUserInterfaceSetting, start_in_tray),
210 UG_ENTRY_BOOL, NULL, NULL},
211 {"CloseToTray", offsetof (struct UgtkUserInterfaceSetting, close_to_tray),
212 UG_ENTRY_BOOL, NULL, NULL},
213 {"StartInOfflineMode", offsetof (struct UgtkUserInterfaceSetting, start_in_offline_mode),
214 UG_ENTRY_BOOL, NULL, NULL},
215 {"StartNotification", offsetof (struct UgtkUserInterfaceSetting, start_notification),
216 UG_ENTRY_BOOL, NULL, NULL},
217 {"SoundNotification", offsetof (struct UgtkUserInterfaceSetting, sound_notification),
218 UG_ENTRY_BOOL, NULL, NULL},
219 {"ApplyRecently", offsetof (struct UgtkUserInterfaceSetting, apply_recent),
220 UG_ENTRY_BOOL, NULL, NULL},
221 {"ApplyRecent", offsetof (struct UgtkUserInterfaceSetting, apply_recent),
222 UG_ENTRY_BOOL, NULL, NULL},
223 {"SkipExisting", offsetof (struct UgtkUserInterfaceSetting, skip_existing),
224 UG_ENTRY_BOOL, NULL, NULL},
225 {"LargeIcon", offsetof (struct UgtkUserInterfaceSetting, large_icon),
226 UG_ENTRY_BOOL, NULL, NULL},
227 #ifdef HAVE_APP_INDICATOR
228 {"AppIndicator", offsetof (struct UgtkUserInterfaceSetting, app_indicator),
229 UG_ENTRY_BOOL, NULL, NULL},
230 #endif
231 {NULL}, // null-terminated
232 };
233
234 // ----------------------------------------------------------------------------
235 // ClipboardSetting
236
237 static const UgEntry UgtkClipboardSettingEntry[] =
238 {
239 {"pattern", offsetof (struct UgtkClipboardSetting, pattern),
240 UG_ENTRY_STRING, NULL, NULL},
241 {"monitor", offsetof (struct UgtkClipboardSetting, monitor),
242 UG_ENTRY_BOOL, NULL, NULL},
243 {"quiet", offsetof (struct UgtkClipboardSetting, quiet),
244 UG_ENTRY_BOOL, NULL, NULL},
245 {"NthCategory", offsetof (struct UgtkClipboardSetting, nth_category),
246 UG_ENTRY_INT, NULL, NULL},
247
248 {"Website", offsetof (struct UgtkClipboardSetting, website),
249 UG_ENTRY_BOOL, NULL, NULL},
250
251 // remove this in future verison
252 {"MediaWebsite", offsetof (struct UgtkClipboardSetting, website),
253 UG_ENTRY_BOOL, NULL, NULL},
254 {NULL}, // null-terminated
255 };
256
257 // ----------------------------------------------------------------------------
258 // BandwidthSetting
259
260 static const UgEntry UgtkBandwidthSettingEntry[] =
261 {
262 {"NormalUpload", offsetof (struct UgtkBandwidthSetting, normal.upload),
263 UG_ENTRY_INT, NULL, NULL},
264 {"NormalDownload", offsetof (struct UgtkBandwidthSetting, normal.download),
265 UG_ENTRY_INT, NULL, NULL},
266 {"SchedulerUpload", offsetof (struct UgtkBandwidthSetting, scheduler.upload),
267 UG_ENTRY_INT, NULL, NULL},
268 {"SchedulerDownload", offsetof (struct UgtkBandwidthSetting, scheduler.download),
269 UG_ENTRY_INT, NULL, NULL},
270 {NULL}, // null-terminated
271 };
272
273 // ----------------------------------------------------------------------------
274 // SchedulerSetting
275
276 static const UgEntry UgtkSchedulerSettingEntry[] =
277 {
278 {"enable", offsetof (struct UgtkSchedulerSetting, enable),
279 UG_ENTRY_BOOL, NULL, NULL},
280 {"state", offsetof (struct UgtkSchedulerSetting, state),
281 UG_ENTRY_ARRAY, ug_json_parse_array_int, ug_json_write_array_int},
282 {NULL}, // null-terminated
283 };
284
285 // ----------------------------------------------------------------------------
286 // CommandlineSetting
287
288 static const UgEntry UgtkCommandlineSettingEntry[] =
289 {
290 {"quiet", offsetof (struct UgtkCommandlineSetting, quiet),
291 UG_ENTRY_BOOL, NULL, NULL},
292 {"NthCategory", offsetof (struct UgtkCommandlineSetting, nth_category),
293 UG_ENTRY_INT, NULL, NULL},
294 {NULL}, // null-terminated
295 };
296
297 // ----------------------------------------------------------------------------
298 // PluginAria2Setting
299
300 static const UgEntry UgtkPluginAria2SettingEntry[] =
301 {
302 {"launch", offsetof (struct UgtkPluginAria2Setting, launch),
303 UG_ENTRY_BOOL, NULL, NULL},
304 {"shutdown", offsetof (struct UgtkPluginAria2Setting, shutdown),
305 UG_ENTRY_BOOL, NULL, NULL},
306 {"token", offsetof (struct UgtkPluginAria2Setting, token),
307 UG_ENTRY_STRING, NULL, NULL},
308 {"path", offsetof (struct UgtkPluginAria2Setting, path),
309 UG_ENTRY_STRING, NULL, NULL},
310 {"arguments", offsetof (struct UgtkPluginAria2Setting, args),
311 UG_ENTRY_STRING, NULL, NULL},
312 {"uri", offsetof (struct UgtkPluginAria2Setting, uri),
313 UG_ENTRY_STRING, NULL, NULL},
314 {"MaxUploadSpeed", offsetof (struct UgtkPluginAria2Setting, limit.upload),
315 UG_ENTRY_INT, NULL, NULL},
316 {"MaxDownloadSpeed", offsetof (struct UgtkPluginAria2Setting, limit.download),
317 UG_ENTRY_INT, NULL, NULL},
318 {NULL}, // null-terminated
319 };
320
321 // ----------------------------------------------------------------------------
322 // PluginMediaSetting
323
324 static const UgEntry UgtkPluginMediaSettingEntry[] =
325 {
326 {"match_mode", offsetof (struct UgtkPluginMediaSetting, match_mode),
327 UG_ENTRY_INT, NULL, NULL},
328 {"quality", offsetof (struct UgtkPluginMediaSetting, quality),
329 UG_ENTRY_INT, NULL, NULL},
330 {"type", offsetof (struct UgtkPluginMediaSetting, type),
331 UG_ENTRY_INT, NULL, NULL},
332 {NULL}, // null-terminated
333 };
334
335 // ----------------------------------------------------------------------------
336 // UgtkCompletionSetting
337
338 static const UgEntry UgtkCompletionSettingEntry[] =
339 {
340 {"remember", offsetof (struct UgtkCompletionSetting, remember),
341 UG_ENTRY_BOOL, NULL, NULL},
342 {"action", offsetof (struct UgtkCompletionSetting, action),
343 UG_ENTRY_INT, NULL, NULL},
344 {"command", offsetof (struct UgtkCompletionSetting, command),
345 UG_ENTRY_STRING, NULL, NULL},
346 {"OnError", offsetof (struct UgtkCompletionSetting, on_error),
347 UG_ENTRY_STRING, NULL, NULL},
348 {NULL}, // null-terminated
349 };
350
351 // ----------------------------------------------------------------------------
352 // UgtkSetting
353
354 static const UgEntry UgtkSettingEntry[] =
355 {
356 {"Window", offsetof (UgtkSetting, window),
357 UG_ENTRY_OBJECT, (void*) UgtkWindowSettingEntry, NULL},
358 {"Summary", offsetof (UgtkSetting, summary),
359 UG_ENTRY_OBJECT, (void*) UgtkSummarySettingEntry, NULL},
360 {"DownloadColumn", offsetof (UgtkSetting, download_column),
361 UG_ENTRY_OBJECT, (void*) UgtkDownloadColumnSettingEntry, NULL},
362 {"UserInterface", offsetof (UgtkSetting, ui),
363 UG_ENTRY_OBJECT, (void*) UgtkUserInterfaceSettingEntry, NULL},
364 {"Clipboard", offsetof (UgtkSetting, clipboard),
365 UG_ENTRY_OBJECT, (void*) UgtkClipboardSettingEntry, NULL},
366 {"Bandwidth", offsetof (UgtkSetting, bandwidth),
367 UG_ENTRY_OBJECT, (void*) UgtkBandwidthSettingEntry, NULL},
368 {"Commandline", offsetof (UgtkSetting, commandline),
369 UG_ENTRY_OBJECT, (void*) UgtkCommandlineSettingEntry, NULL},
370
371 {"PluginOrder", offsetof (UgtkSetting, plugin_order),
372 UG_ENTRY_INT, NULL, NULL},
373 {"PluginAria2", offsetof (UgtkSetting, aria2),
374 UG_ENTRY_OBJECT, (void*) UgtkPluginAria2SettingEntry, NULL},
375 {"PluginMedia", offsetof (UgtkSetting, media),
376 UG_ENTRY_OBJECT, (void*) UgtkPluginMediaSettingEntry, NULL},
377
378 {"Completion", offsetof (UgtkSetting, completion),
379 UG_ENTRY_OBJECT, (void*) UgtkCompletionSettingEntry, NULL},
380
381 {"FolderHistory", offsetof (UgtkSetting, folder_history),
382 UG_ENTRY_ARRAY, ug_json_parse_list_string, ug_json_write_list_string},
383
384 {"AutoSave", offsetof (UgtkSetting, auto_save.enable),
385 UG_ENTRY_INT, NULL, NULL},
386 {"AutoSaveInterval",offsetof (UgtkSetting, auto_save.interval),
387 UG_ENTRY_INT, NULL, NULL},
388 // {"OfflineMode", offsetof (UgtkSetting, offline_mode),
389 // UG_ENTRY_BOOL, NULL, NULL},
390
391 {"Scheduler", offsetof (UgtkSetting, scheduler),
392 UG_ENTRY_OBJECT, (void*) UgtkSchedulerSettingEntry, NULL},
393 {NULL}, // null-terminated
394 };
395
396 // ----------------------------------------------------------------------------
397 // "UgSetting" functions
398 //
ugtk_setting_init(UgtkSetting * setting)399 void ugtk_setting_init (UgtkSetting* setting)
400 {
401 // "SchedulerSetting"
402 ug_array_init (&setting->scheduler.state, sizeof (int), 7*24);
403 memset (setting->scheduler.state.at, UGTK_SCHEDULE_NORMAL, 7*24);
404
405 // default settings for media (or storage) website
406 setting->clipboard.website = TRUE;
407 setting->media.match_mode = UGET_MEDIA_MATCH_NEAR;
408 setting->media.quality = UGET_MEDIA_QUALITY_360P;
409 setting->media.type = UGET_MEDIA_TYPE_MP4;
410 }
411
ugtk_setting_reset(UgtkSetting * setting)412 void ugtk_setting_reset (UgtkSetting* setting)
413 {
414 unsigned int weekdays, dayhours;
415
416 // "WindowSetting"
417 setting->window.toolbar = TRUE;
418 setting->window.statusbar = TRUE;
419 setting->window.category = TRUE;
420 setting->window.summary = TRUE;
421 setting->window.banner = TRUE;
422 setting->window.x = 0;
423 setting->window.y = 0;
424 setting->window.width = 0;
425 setting->window.height = 0;
426 setting->window.maximized = FALSE;
427 setting->window.paned_position_h = -1;
428 setting->window.paned_position_v = -1;
429
430 // "SummarySetting"
431 setting->summary.name = TRUE;
432 setting->summary.folder = TRUE;
433 setting->summary.category = FALSE;
434 setting->summary.uri = FALSE;
435 setting->summary.message = TRUE;
436
437 // "DownloadColumnSetting"
438 setting->download_column.complete = TRUE;
439 setting->download_column.total = TRUE;
440 setting->download_column.percent = TRUE;
441 setting->download_column.elapsed = TRUE;
442 setting->download_column.left = TRUE;
443 setting->download_column.speed = TRUE;
444 setting->download_column.upload_speed = TRUE;
445 setting->download_column.uploaded = FALSE;
446 setting->download_column.ratio = TRUE;
447 setting->download_column.retry = TRUE;
448 setting->download_column.category = FALSE;
449 setting->download_column.uri = FALSE;
450 setting->download_column.added_on = TRUE;
451 setting->download_column.completed_on = FALSE;
452 // default sorted column
453 setting->download_column.sort.type = GTK_SORT_DESCENDING;
454 setting->download_column.sort.nth = UGTK_NODE_COLUMN_STATE;
455 // "DownloadColumnWidth"
456 memset (&setting->download_column.width, 0,
457 sizeof (setting->download_column.width));
458
459 // "UserInterfaceSetting"
460 setting->ui.exit_confirmation = TRUE;
461 setting->ui.delete_confirmation = TRUE;
462 setting->ui.show_trayicon = TRUE;
463 setting->ui.start_in_tray = FALSE;
464 setting->ui.close_to_tray = TRUE;
465 setting->ui.start_in_offline_mode = FALSE;
466 setting->ui.start_notification = TRUE;
467 setting->ui.sound_notification = TRUE;
468 setting->ui.apply_recent = TRUE;
469 setting->ui.skip_existing = FALSE;
470 setting->ui.large_icon = FALSE;
471 #ifdef HAVE_APP_INDICATOR
472 setting->ui.app_indicator = TRUE;
473 #endif
474
475 // "ClipboardSetting"
476 ug_free (setting->clipboard.pattern);
477 setting->clipboard.pattern = ug_strdup (UGTK_APP_CLIPBOARD_PATTERN);
478 setting->clipboard.monitor = TRUE;
479 setting->clipboard.quiet = FALSE;
480 setting->clipboard.nth_category = 0;
481 setting->clipboard.website = TRUE;
482
483 // "BandwidthSetting"
484 setting->bandwidth.normal.upload = 0;
485 setting->bandwidth.normal.download = 0;
486 setting->bandwidth.scheduler.upload = 0;
487 setting->bandwidth.scheduler.download = 0;
488
489 // "SchedulerSetting"
490 setting->scheduler.enable = FALSE;
491 ug_array_init (&setting->scheduler.state, sizeof (int), 7*24);
492 setting->scheduler.state.length = 7 * 24;
493 for (weekdays = 0; weekdays < 7; weekdays++) {
494 for (dayhours = 0; dayhours < 24; dayhours++) {
495 setting->scheduler.state.at[weekdays*24 + dayhours] =
496 UGTK_SCHEDULE_NORMAL;
497 }
498 }
499
500 // "CommandlineSetting"
501 setting->commandline.quiet = FALSE;
502 setting->commandline.nth_category = 0;
503
504 // "PluginSetting"
505 setting->plugin_order = UGTK_PLUGIN_ORDER_CURL;
506 // aria2 plug-in settings
507 setting->aria2.limit.download = 0;
508 setting->aria2.limit.upload = 0;
509 setting->aria2.launch = TRUE;
510 setting->aria2.shutdown = TRUE;
511 setting->aria2.path = ug_strdup (UGTK_ARIA2_PATH);
512 setting->aria2.args = ug_strdup (UGTK_ARIA2_ARGS);
513 setting->aria2.uri = ug_strdup (UGTK_ARIA2_URI);
514 // media plug-in settings
515 setting->media.match_mode = UGET_MEDIA_MATCH_NEAR;
516 setting->media.quality = UGET_MEDIA_QUALITY_360P;
517 setting->media.type = UGET_MEDIA_TYPE_MP4;
518
519 // Others
520 setting->completion.remember = TRUE;
521 setting->completion.action = 0;
522 setting->completion.command = NULL;
523 setting->completion.on_error = NULL;
524 setting->auto_save.enable = TRUE;
525 setting->auto_save.interval = 3;
526
527 setting->offline_mode = FALSE;
528 }
529
530 // ----------------------------------------------------------------------------
531 // save/load settings
532
ugtk_setting_save(UgtkSetting * setting,const char * file)533 int ugtk_setting_save (UgtkSetting* setting, const char* file)
534 {
535 int action;
536 char* path;
537 UgJsonFile* jfile;
538
539 path = g_strconcat (file, ".temp", NULL);
540 jfile = ug_json_file_new (4096);
541 if (ug_json_file_begin_write (jfile, path, UG_JSON_FORMAT_ALL) == FALSE) {
542 ug_json_file_free (jfile);
543 g_free (path);
544 return FALSE;
545 }
546
547 // save completion.action
548 action = setting->completion.action;
549 if (setting->completion.remember == FALSE)
550 setting->completion.action = 0;
551
552 ug_json_write_object_head (&jfile->json);
553 ug_json_write_entry (&jfile->json, setting, UgtkSettingEntry);
554 ug_json_write_object_tail (&jfile->json);
555
556 // restore completion.action
557 if (setting->completion.remember == FALSE)
558 setting->completion.action = action;
559
560 ug_json_file_end_write (jfile);
561 ug_json_file_free (jfile);
562
563 ug_remove (file);
564 ug_rename (path, file);
565 g_free (path);
566
567 return TRUE;
568 }
569
ugtk_setting_load(UgtkSetting * setting,const char * path)570 int ugtk_setting_load (UgtkSetting* setting, const char* path)
571 {
572 int file_ok;
573 char* path_temp;
574 UgJsonFile* jfile;
575
576 path_temp = g_strconcat (path, ".temp", NULL);
577 jfile = ug_json_file_new (4096);
578 file_ok = ug_json_file_begin_parse (jfile, path);
579 if (file_ok)
580 ug_remove (path_temp);
581 else if (ug_rename (path_temp, path) != -1)
582 file_ok = ug_json_file_begin_parse (jfile, path);
583 g_free (path_temp);
584
585 if (file_ok == FALSE) {
586 ug_json_file_free (jfile);
587 return FALSE;
588 }
589
590 ug_json_push (&jfile->json, ug_json_parse_entry,
591 setting, (void*) UgtkSettingEntry);
592 ug_json_push (&jfile->json, ug_json_parse_object,
593 NULL, NULL);
594
595 ug_json_file_end_parse (jfile);
596 ug_json_file_free (jfile);
597
598 // check & fix settings
599 ugtk_setting_fix_data (setting);
600 return TRUE;
601 }
602
ugtk_setting_add_folder(UgtkSetting * setting,const char * folder)603 void ugtk_setting_add_folder (UgtkSetting* setting, const char* folder)
604 {
605 UgList* list;
606 UgLink* link;
607
608 if (folder == NULL || folder[0] == 0)
609 return;
610
611 list = &setting->folder_history;
612 for (link = list->head; link; link = link->next) {
613 if (strcmp (folder, link->data) == 0) {
614 ug_list_remove (list, link);
615 ug_list_prepend (list, link);
616 return;
617 }
618 }
619
620 if (list->size >= 8) {
621 link = list->tail;
622 ug_list_remove (list, link);
623 ug_free (link->data);
624 ug_link_free (link);
625 }
626 link = ug_link_new ();
627 link->data = ug_strdup (folder);
628 ug_list_prepend (list, link);
629 }
630
ugtk_setting_fix_data(UgtkSetting * setting)631 void ugtk_setting_fix_data (UgtkSetting* setting)
632 {
633 unsigned int index;
634
635 // "DownloadColumnSetting"
636 // default sorted column
637 if (setting->download_column.sort.type != GTK_SORT_ASCENDING &&
638 setting->download_column.sort.type != GTK_SORT_DESCENDING)
639 {
640 setting->download_column.sort.type = GTK_SORT_DESCENDING;
641 }
642 if (setting->download_column.sort.nth < 0 ||
643 setting->download_column.sort.nth >= UGTK_NODE_N_COLUMNS)
644 {
645 setting->download_column.sort.nth = UGTK_NODE_COLUMN_ADDED_ON;
646 }
647
648 // "ClipboardSetting"
649 if (setting->clipboard.pattern == NULL ||
650 setting->clipboard.pattern[0] == 0)
651 {
652 ug_free (setting->clipboard.pattern);
653 setting->clipboard.pattern = ug_strdup (UGTK_APP_CLIPBOARD_PATTERN);
654 }
655
656 // "SchedulerSetting"
657 for (index = 0; index < 7*24; index++) {
658 if (setting->scheduler.state.at[index] < 0 ||
659 setting->scheduler.state.at[index] >= UGTK_SCHEDULE_N_STATE)
660 {
661 setting->scheduler.state.at[index] = UGTK_SCHEDULE_NORMAL;
662 }
663 }
664
665 // "PluginSetting"
666 if (setting->plugin_order < 0 ||
667 setting->plugin_order >= UGTK_PLUGIN_N_ORDER)
668 {
669 setting->plugin_order = UGTK_PLUGIN_ORDER_CURL;
670 }
671 // aria2 plug-in settings
672 if (setting->aria2.path == NULL || setting->aria2.path[0] == 0) {
673 ug_free (setting->aria2.path);
674 setting->aria2.path = ug_strdup (UGTK_ARIA2_PATH);
675 }
676 if (setting->aria2.args == NULL || setting->aria2.args[0] == 0) {
677 ug_free (setting->aria2.args);
678 setting->aria2.args = ug_strdup (UGTK_ARIA2_ARGS);
679 }
680 if (setting->aria2.uri == NULL || setting->aria2.uri[0] == 0) {
681 ug_free (setting->aria2.uri);
682 setting->aria2.uri = ug_strdup (UGTK_ARIA2_URI);
683 }
684 // media plug-in settings
685 if (setting->media.match_mode < 0 || setting->media.match_mode > UGET_MEDIA_N_MATCH_MODE)
686 setting->media.match_mode = UGET_MEDIA_MATCH_NEAR;
687 if (setting->media.quality < 0 || setting->media.quality > UGET_MEDIA_N_QUALITY)
688 setting->media.quality = UGET_MEDIA_QUALITY_360P;
689 if (setting->media.type < 0 || setting->media.type > UGET_MEDIA_N_TYPE)
690 setting->media.type = UGET_MEDIA_TYPE_MP4;
691 }
692