From e2bc6f4153813cc570ae814c8ddb74628009b488 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Mon, 13 Apr 2015 09:21:39 +0200 Subject: initial checkin Check in contents of upstream 1.4.2 tarball, exclude generated files. --- src/sys_settings.cpp | 2048 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2048 insertions(+) create mode 100644 src/sys_settings.cpp (limited to 'src/sys_settings.cpp') diff --git a/src/sys_settings.cpp b/src/sys_settings.cpp new file mode 100644 index 0000000..36e7142 --- /dev/null +++ b/src/sys_settings.cpp @@ -0,0 +1,2048 @@ +/* + Copyright (C) 2005-2009 Michel de Boer + + 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; either version 2 of the License, or + (at your option) any later version. + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "twinkle_config.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys_settings.h" + +#include "log.h" +#include "translator.h" +#include "user.h" +#include "userintf.h" +#include "util.h" +#include "audits/memman.h" +#include "utils/file_utils.h" + +using namespace utils; + +// Share directory containing files applicable to all users +#define DIR_SHARE DATADIR + +// Lock file to guarantee that a user is running the application only once +#define LOCK_FILENAME "twinkle.lck" + +// System config file +#define SYS_CONFIG_FILE "twinkle.sys" + +// Default location of the shared mime database +#define DFLT_SHARED_MIME_DB "/usr/share/mime/globs" + +// Field names in the config file +// AUDIO fields +#define FLD_DEV_RINGTONE "dev_ringtone" +#define FLD_DEV_SPEAKER "dev_speaker" +#define FLD_DEV_MIC "dev_mic" +#define FLD_VALIDATE_AUDIO_DEV "validate_audio_dev" +#define FLD_ALSA_PLAY_PERIOD_SIZE "alsa_play_period_size" +#define FLD_ALSA_CAPTURE_PERIOD_SIZE "alsa_capture_period_size" +#define FLD_OSS_FRAGMENT_SIZE "oss_fragment_size" + +// LOG fields +#define FLD_LOG_MAX_SIZE "log_max_size" +#define FLD_LOG_SHOW_SIP "log_show_sip" +#define FLD_LOG_SHOW_STUN "log_show_stun" +#define FLD_LOG_SHOW_MEMORY "log_show_memory" +#define FLD_LOG_SHOW_DEBUG "log_show_debug" + +// GUI settings +#define FLD_GUI_USE_SYSTRAY "gui_use_systray" +#define FLD_GUI_HIDE_ON_CLOSE "gui_hide_on_close" +#define FLD_GUI_AUTO_SHOW_INCOMING "gui_auto_show_incoming" +#define FLD_GUI_AUTO_SHOW_TIMEOUT "gui_auto_show_timeout" +#define FLD_GUI_BROWSER_CMD "gui_browser_cmd" + +// Address book settings +#define FLD_AB_SHOW_SIP_ONLY "ab_show_sip_only" +#define FLD_AB_LOOKUP_NAME "ab_lookup_name" +#define FLD_AB_OVERRIDE_DISPLAY "ab_override_display" +#define FLD_AB_LOOKUP_PHOTO "ab_lookup_photo" + +// Call history fields +#define FLD_CH_MAX_SIZE "ch_max_size" + +// Service settings +#define FLD_CALL_WAITING "call_waiting" +#define FLD_HANGUP_BOTH_3WAY "hangup_both_3way" + +// Startup settings +#define FLD_START_USER_PROFILE "start_user_profile" +#define FLD_START_HIDDEN "start_hidden" + +// Network settings +#define FLD_sip_udp_port "sip_udp_port" +#define FLD_sip_port "sip_port" +#define FLD_RTP_PORT "rtp_port" +#define FLD_SIP_MAX_UDP_SIZE "sip_max_udp_size" +#define FLD_SIP_MAX_TCP_SIZE "sip_max_tcp_size" + +// Ring tone settings +#define FLD_PLAY_RINGTONE "play_ringtone" +#define FLD_RINGTONE_FILE "ringtone_file" +#define FLD_PLAY_RINGBACK "play_ringback" +#define FLD_RINGBACK_FILE "ringback_file" + +// Persistent storage for user interface state +#define FLD_LAST_USED_PROFILE "last_used_profile" +#define FLD_REDIAL_URL "redial_url" +#define FLD_REDIAL_DISPLAY "redial_display" +#define FLD_REDIAL_SUBJECT "redial_subject" +#define FLD_REDIAL_PROFILE "redial_profile" +#define FLD_REDIAL_HIDE_USER "redial_hide_user" +#define FLD_DIAL_HISTORY "dial_history" +#define FLD_SHOW_DISPLAY "show_display" +#define FLD_COMPACT_LINE_STATUS "compact_line_status" +#define FLD_SHOW_BUDDY_LIST "show_buddy_list" +#define FLD_WARN_HIDE_USER "warn_hide_user" + +// Settings to restore session after shutdown +#define FLD_UI_SESSION_ID "ui_session_id" +#define FLD_UI_SESSION_ACTIVE_PROFILE "ui_session_active_profile" +#define FLD_UI_SESSION_MAIN_GEOMETRY "ui_session_main_geometry" +#define FLD_UI_SESSION_MAIN_HIDDEN "ui_session_main_hidden" +#define FLD_UI_SESSION_MAIN_STATE "ui_session_main_state" + +// Mime settings +#define FLD_MIME_SHARED_DATABASE "mime_shared_database" + +///////////////////////// +// class t_audio_device +///////////////////////// + +string t_audio_device::get_description(void) const { + string s = device; + if (type == OSS) { + s = "OSS: " + s; + if (sym_link.size() > 0) { + s += " -> "; + s += sym_link; + } + + if (name.size() > 0) { + s += ": "; + s += name; + } + } else if (type == ALSA) { + s = "ALSA: " + s; + if (!name.empty()) { + s += ": "; + s += name; + } + } else { + s = "Unknown: " + s; + } + + return s; +} + +string t_audio_device::get_settings_value(void) const { + string s; + + switch (type) { + case OSS: + s = PFX_OSS; + break; + case ALSA: + s = PFX_ALSA; + break; + default: + assert(false); + } + + s += device; + return s; +} + +///////////////////////// +// class t_win_geometry +///////////////////////// + +t_win_geometry::t_win_geometry(int x_, int y_, int width_, int height_) : + x(x_), y(y_), width(width_), height(height_) +{} + +t_win_geometry::t_win_geometry() : + x(0), y(0), width(0), height(0) +{} + +t_win_geometry::t_win_geometry(const string &value) { + vector v = split(value, ','); + + if (v.size() == 4) { + x = atoi(v[0].c_str()); + y = atoi(v[1].c_str()); + width = atoi(v[2].c_str()); + height = atoi(v[3].c_str()); + } +} + +string t_win_geometry::encode(void) const { + string s; + + s = int2str(x); + s += ','; + s += int2str(y); + s += ','; + s += int2str(width); + s += ','; + s += int2str(height); + + return s; +} + + +///////////////////////// +// class t_sys_settings +///////////////////////// + +t_sys_settings::t_sys_settings() { + fd_lock_file = -1; + dir_share = DIR_SHARE; + filename = string(DIR_HOME); + filename += "/"; + filename += USER_DIR; + filename += "/"; + filename += SYS_CONFIG_FILE; + + // Audio device default settings +#ifdef HAVE_LIBASOUND + dev_ringtone = audio_device(DEV_ALSA_DFLT); + dev_speaker = audio_device(DEV_ALSA_DFLT); + dev_mic = audio_device(DEV_ALSA_DFLT); +#else + dev_ringtone = audio_device(); + dev_speaker = audio_device(); + dev_mic = audio_device(); +#endif + validate_audio_dev = true; + alsa_play_period_size = 128; + alsa_capture_period_size = 32; + oss_fragment_size = 128; + + log_max_size = 5; + log_show_sip = true; + log_show_stun = true; + log_show_memory = true; + log_show_debug = false; + + gui_use_systray = true; + gui_hide_on_close = true; + gui_auto_show_incoming = false; + gui_auto_show_timeout = 10; + + ab_show_sip_only = false; + ab_lookup_name = true; + ab_override_display = true; + ab_lookup_photo = true; + + ch_max_size = 50; + + call_waiting = true; + hangup_both_3way = true; + + start_user_profiles.clear(); + start_hidden = false; + + config_sip_port = 5060; + active_sip_port = 0; + override_sip_port = 0; + rtp_port = 8000; + override_rtp_port = 0; + sip_max_udp_size = 65535; + sip_max_tcp_size = 1000000; + + play_ringtone = true; + ringtone_file.clear(); + play_ringback = true; + ringback_file.clear(); + + last_used_profile.clear(); + redial_url.set_url(""); + redial_display.clear(); + redial_subject.clear(); + redial_profile.clear(); + redial_hide_user = false; + dial_history.clear(); + show_display = true; + compact_line_status = false; + show_buddy_list = true; + warn_hide_user = true; + + ui_session_id.clear(); + + mime_shared_database = DFLT_SHARED_MIME_DB; +} + +// Getters +t_audio_device t_sys_settings::get_dev_ringtone(void) const { + t_audio_device result; + mtx_sys.lock(); + result = dev_ringtone; + mtx_sys.unlock(); + return result; +} + +t_audio_device t_sys_settings::get_dev_speaker(void) const { + t_audio_device result; + mtx_sys.lock(); + result = dev_speaker; + mtx_sys.unlock(); + return result; +} + +t_audio_device t_sys_settings::get_dev_mic(void) const { + t_audio_device result; + mtx_sys.lock(); + result = dev_mic; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_validate_audio_dev(void) const { + bool result; + mtx_sys.lock(); + result = validate_audio_dev; + mtx_sys.unlock(); + return result; +} + +int t_sys_settings::get_alsa_play_period_size(void) const { + int result; + mtx_sys.lock(); + result = alsa_play_period_size; + mtx_sys.unlock(); + return result; +} + +int t_sys_settings::get_alsa_capture_period_size(void) const { + int result; + mtx_sys.lock(); + result = alsa_capture_period_size; + mtx_sys.unlock(); + return result; +} + +int t_sys_settings::get_oss_fragment_size(void) const { + int result; + mtx_sys.lock(); + result = oss_fragment_size; + mtx_sys.unlock(); + return result; +} + +unsigned short t_sys_settings::get_log_max_size(void) const { + unsigned short result; + mtx_sys.lock(); + result = log_max_size; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_log_show_sip(void) const { + bool result; + mtx_sys.lock(); + result = log_show_sip; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_log_show_stun(void) const { + bool result; + mtx_sys.lock(); + result = log_show_stun; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_log_show_memory(void) const { + bool result; + mtx_sys.lock(); + result = log_show_memory; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_log_show_debug(void) const { + bool result; + mtx_sys.lock(); + result = log_show_debug; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_gui_use_systray(void) const { + t_mutex_guard guard(mtx_sys); + return gui_use_systray; +} + +bool t_sys_settings::get_gui_auto_show_incoming(void) const { + t_mutex_guard guard(mtx_sys); + return gui_auto_show_incoming; +} + +int t_sys_settings::get_gui_auto_show_timeout(void) const { + t_mutex_guard guard(mtx_sys); + return gui_auto_show_timeout; +} + +bool t_sys_settings::get_gui_hide_on_close(void) const { + t_mutex_guard guard(mtx_sys); + return gui_hide_on_close; +} + +string t_sys_settings::get_gui_browser_cmd(void) const { + t_mutex_guard guard(mtx_sys); + return gui_browser_cmd; +} + +bool t_sys_settings::get_ab_show_sip_only(void) const { + bool result; + mtx_sys.lock(); + result = ab_show_sip_only; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_ab_lookup_name(void) const { + bool result; + mtx_sys.lock(); + result = ab_lookup_name; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_ab_override_display(void) const { + bool result; + mtx_sys.lock(); + result = ab_override_display; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_ab_lookup_photo(void) const { + bool result; + mtx_sys.lock(); + result = ab_lookup_photo; + mtx_sys.unlock(); + return result; +} + +int t_sys_settings::get_ch_max_size(void) const { + int result; + mtx_sys.lock(); + result = ch_max_size; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_call_waiting(void) const { + bool result; + mtx_sys.lock(); + result = call_waiting; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_hangup_both_3way(void) const { + bool result; + mtx_sys.lock(); + result = hangup_both_3way; + mtx_sys.unlock(); + return result; +} + +list t_sys_settings::get_start_user_profiles(void) const { + list result; + mtx_sys.lock(); + result = start_user_profiles; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_start_hidden(void) const { + bool result; + mtx_sys.lock(); + result = start_hidden; + mtx_sys.unlock(); + return result; +} + +unsigned short t_sys_settings::get_config_sip_port(void) const { + unsigned short result; + mtx_sys.lock(); + result = config_sip_port; + mtx_sys.unlock(); + return result; +} + +unsigned short t_sys_settings::get_rtp_port(void) const { + unsigned short result; + mtx_sys.lock(); + if (override_rtp_port > 0) { + result = override_rtp_port; + } else { + result = rtp_port; + } + mtx_sys.unlock(); + return result; +} + +unsigned short t_sys_settings::get_sip_max_udp_size(void) const { + t_mutex_guard guard(mtx_sys); + return sip_max_udp_size; +} + +unsigned long t_sys_settings::get_sip_max_tcp_size(void) const { + t_mutex_guard guard(mtx_sys); + return sip_max_tcp_size; +} + +bool t_sys_settings::get_play_ringtone(void) const { + bool result; + mtx_sys.lock(); + result = play_ringtone; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_ringtone_file(void) const { + string result; + mtx_sys.lock(); + result = ringtone_file; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_play_ringback(void) const { + bool result; + mtx_sys.lock(); + result = play_ringback; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_ringback_file(void) const { + string result; + mtx_sys.lock(); + result = ringback_file; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_last_used_profile(void) const { + string result; + mtx_sys.lock(); + result = last_used_profile; + mtx_sys.unlock(); + return result; +} + +t_url t_sys_settings::get_redial_url(void) const { + t_url result; + mtx_sys.lock(); + result = redial_url; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_redial_display(void) const { + string result; + mtx_sys.lock(); + result = redial_display; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_redial_subject(void) const { + string result; + mtx_sys.lock(); + result = redial_subject; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_redial_profile(void) const { + string result; + mtx_sys.lock(); + result = redial_profile; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_redial_hide_user(void) const { + bool result; + mtx_sys.lock(); + result = redial_hide_user; + mtx_sys.unlock(); + return result; +} + +list t_sys_settings::get_dial_history(void) const { + list result; + mtx_sys.lock(); + result = dial_history; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_show_display(void) const { + bool result; + mtx_sys.lock(); + result = show_display; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_compact_line_status(void) const { + bool result; + mtx_sys.lock(); + result = compact_line_status; + mtx_sys.unlock(); + return result; +} + +bool t_sys_settings::get_show_buddy_list(void) const { + bool result; + mtx_sys.lock(); + result = show_buddy_list; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_ui_session_id(void) const { + t_mutex_guard guard(mtx_sys); + return ui_session_id; +} + +list t_sys_settings::get_ui_session_active_profiles(void) const { + t_mutex_guard guard(mtx_sys); + return ui_session_active_profiles; +} + +t_win_geometry t_sys_settings::get_ui_session_main_geometry(void) const { + t_mutex_guard guard(mtx_sys); + return ui_session_main_geometry; +} + +bool t_sys_settings::get_ui_session_main_hidden(void) const { + t_mutex_guard guard(mtx_sys); + return ui_session_main_hidden; +} + +unsigned int t_sys_settings::get_ui_session_main_state(void) const { + t_mutex_guard guard(mtx_sys); + return ui_session_main_state; +} + +bool t_sys_settings::get_warn_hide_user(void) const { + t_mutex_guard guard(mtx_sys); + return warn_hide_user; +} + +string t_sys_settings::get_mime_shared_database(void) const { + t_mutex_guard guard(mtx_sys); + return mime_shared_database; +} + +// Setters +void t_sys_settings::set_dev_ringtone(const t_audio_device &dev) { + mtx_sys.lock(); + dev_ringtone = dev; + mtx_sys.unlock(); +} + +void t_sys_settings::set_dev_speaker(const t_audio_device &dev) { + mtx_sys.lock(); + dev_speaker = dev; + mtx_sys.unlock(); +} + +void t_sys_settings::set_dev_mic(const t_audio_device &dev) { + mtx_sys.lock(); + dev_mic = dev; + mtx_sys.unlock(); +} + +void t_sys_settings::set_validate_audio_dev(bool b) { + mtx_sys.lock(); + validate_audio_dev = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_alsa_play_period_size(int size) { + mtx_sys.lock(); + alsa_play_period_size = size; + mtx_sys.unlock(); +} + +void t_sys_settings::set_alsa_capture_period_size(int size) { + mtx_sys.lock(); + alsa_capture_period_size = size; + mtx_sys.unlock(); +} + +void t_sys_settings::set_oss_fragment_size(int size) { + mtx_sys.lock(); + oss_fragment_size = size; + mtx_sys.unlock(); +} + +void t_sys_settings::set_log_max_size(unsigned short size) { + mtx_sys.lock(); + log_max_size = size; + mtx_sys.unlock(); +} + +void t_sys_settings::set_log_show_sip(bool b) { + mtx_sys.lock(); + log_show_sip = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_log_show_stun(bool b) { + mtx_sys.lock(); + log_show_stun = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_log_show_memory(bool b) { + t_mutex_guard guard(mtx_sys); + log_show_memory = b; +} + +void t_sys_settings::set_log_show_debug(bool b) { + t_mutex_guard guard(mtx_sys); + log_show_debug = b; +} + +void t_sys_settings::set_gui_use_systray(bool b) { + t_mutex_guard guard(mtx_sys); + gui_use_systray = b; +} + +void t_sys_settings::set_gui_hide_on_close(bool b) { + t_mutex_guard guard(mtx_sys); + gui_hide_on_close = b; +} + +void t_sys_settings::set_gui_auto_show_incoming(bool b) { + t_mutex_guard guard(mtx_sys); + gui_auto_show_incoming = b; +} + +void t_sys_settings::set_gui_auto_show_timeout(int timeout) { + t_mutex_guard guard(mtx_sys); + gui_auto_show_timeout = timeout; +} + +void t_sys_settings::set_gui_browser_cmd(const string &s) { + t_mutex_guard guard(mtx_sys); + gui_browser_cmd = s; +} + +void t_sys_settings::set_ab_show_sip_only(bool b) { + mtx_sys.lock(); + ab_show_sip_only = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ab_lookup_name(bool b) { + mtx_sys.lock(); + ab_lookup_name = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ab_override_display(bool b) { + mtx_sys.lock(); + ab_override_display = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ab_lookup_photo(bool b) { + mtx_sys.lock(); + ab_lookup_photo = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ch_max_size(int size) { + mtx_sys.lock(); + ch_max_size = size; + mtx_sys.unlock(); +} + +void t_sys_settings::set_call_waiting(bool b) { + mtx_sys.lock(); + call_waiting = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_hangup_both_3way(bool b) { + mtx_sys.lock(); + hangup_both_3way = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_start_user_profiles(const list &profiles) { + mtx_sys.lock(); + start_user_profiles = profiles; + mtx_sys.unlock(); +} + +void t_sys_settings::set_start_hidden(bool b) { + mtx_sys.lock(); + start_hidden = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_config_sip_port(unsigned short port) { + mtx_sys.lock(); + config_sip_port = port; + mtx_sys.unlock(); +} + +void t_sys_settings::set_override_sip_port(unsigned short port) { + mtx_sys.lock(); + override_sip_port = port; + mtx_sys.unlock(); +} + +void t_sys_settings::set_rtp_port(unsigned short port) { + mtx_sys.lock(); + rtp_port = port; + mtx_sys.unlock(); +} + +void t_sys_settings::set_override_rtp_port(unsigned short port) { + mtx_sys.lock(); + override_rtp_port = port; + mtx_sys.unlock(); +} + +void t_sys_settings::set_sip_max_udp_size(unsigned short size) { + t_mutex_guard guard(mtx_sys); + sip_max_udp_size = size; +} + +void t_sys_settings::set_sip_max_tcp_size(unsigned long size) { + t_mutex_guard guard(mtx_sys); + sip_max_tcp_size = size; +} + +void t_sys_settings::set_play_ringtone(bool b) { + mtx_sys.lock(); + play_ringtone = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ringtone_file(const string &file) { + mtx_sys.lock(); + ringtone_file = file; + mtx_sys.unlock(); +} + +void t_sys_settings::set_play_ringback(bool b) { + mtx_sys.lock(); + play_ringback = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ringback_file(const string &file) { + mtx_sys.lock(); + ringback_file = file; + mtx_sys.unlock(); +} + +void t_sys_settings::set_last_used_profile(const string &profile) { + mtx_sys.lock(); + last_used_profile = profile; + mtx_sys.unlock(); +} + +void t_sys_settings::set_redial_url(const t_url &url) { + mtx_sys.lock(); + redial_url = url; + mtx_sys.unlock(); +} + +void t_sys_settings::set_redial_display(const string &display) { + mtx_sys.lock(); + redial_display = display; + mtx_sys.unlock(); +} + +void t_sys_settings::set_redial_subject(const string &subject) { + mtx_sys.lock(); + redial_subject = subject; + mtx_sys.unlock(); +} + +void t_sys_settings::set_redial_profile(const string &profile) { + mtx_sys.lock(); + redial_profile = profile; + mtx_sys.unlock(); +} + +void t_sys_settings::set_redial_hide_user(const bool b) { + mtx_sys.lock(); + redial_hide_user = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_dial_history(const list &history) { + mtx_sys.lock(); + dial_history = history; + mtx_sys.unlock(); +} + +void t_sys_settings::set_show_display(bool b) { + mtx_sys.lock(); + show_display = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_compact_line_status(bool b) { + mtx_sys.lock(); + compact_line_status = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_show_buddy_list(bool b) { + mtx_sys.lock(); + show_buddy_list = b; + mtx_sys.unlock(); +} + +void t_sys_settings::set_ui_session_id(const string &id) { + t_mutex_guard guard(mtx_sys); + ui_session_id = id; +} + +void t_sys_settings::set_ui_session_active_profiles(const list &profiles) { + t_mutex_guard guard(mtx_sys); + ui_session_active_profiles = profiles; +} + +void t_sys_settings::set_ui_session_main_geometry(const t_win_geometry &geometry) { + t_mutex_guard guard(mtx_sys); + ui_session_main_geometry = geometry; +} + +void t_sys_settings::set_ui_session_main_hidden(bool hidden) { + t_mutex_guard guard(mtx_sys); + ui_session_main_hidden = hidden; +} + +void t_sys_settings::set_ui_session_main_state(unsigned int state) { + t_mutex_guard guard(mtx_sys); + ui_session_main_state = state; +} + +void t_sys_settings::set_warn_hide_user(bool b) { + t_mutex_guard guard(mtx_sys); + warn_hide_user = b; +} + +void t_sys_settings::set_mime_shared_database(const string &filename) { + t_mutex_guard guard(mtx_sys); + mime_shared_database = filename; +} + +string t_sys_settings::about(bool html) const { + string s = PRODUCT_NAME; + s += ' '; + s += PRODUCT_VERSION; + s += " - "; + s += get_product_date(); + if (html) s += "
"; + s += "\n"; + + s += "Copyright (C) 2005-2009 "; + s += PRODUCT_AUTHOR; + if (html) s += "
"; + s += "\n"; + + s += "http://www.twinklephone.com"; + if (html) s += "

"; + s += "\n\n"; + + string options_built = get_options_built(); + if (!options_built.empty()) { + s += TRANSLATE("Built with support for:"); + s += " "; + s += options_built; + if (html) s += "

"; + s += "\n\n"; + } + + s += TRANSLATE("Contributions:"); + if (html) s += "
"; + s += "\n"; + + s += "* Werner Dittmann (ZRTP/SRTP)\n"; + if (html) s += "
"; + + s += "* Bogdan Harjoc (AKAv1-MD5, Service-Route)\n"; + if (html) s += "
"; + + s += "* Roman Imankulov (command line editing)\n"; + if (html) s += "
"; + + if (html) { + s += "* Ondrej Moriš (codec preprocessing)
\n"; + } else { + s += "* Ondrej Moris (codec preprocessing)\n"; + } + + if (html) { + s += "* Rickard Petzäll (ALSA)
\n"; + } else { + s += "* Rickard Petzall (ALSA)\n"; + } + + if (html) s += "
"; + s += "\n"; + + s += TRANSLATE("This software contains the following software from 3rd parties:"); + if (html) s += "
"; + s += "\n"; + + s += TRANSLATE("* GSM codec from Jutta Degener and Carsten Bormann, University of Berlin"); + if (html) s += "
"; + s += "\n"; + + s += TRANSLATE("* G.711/G.726 codecs from Sun Microsystems (public domain)"); + if (html) s += "
"; + s += "\n"; + +#ifdef HAVE_ILBC + s += TRANSLATE("* iLBC implementation from RFC 3951 (www.ilbcfreeware.org)"); + if (html) s += "
"; + s += "\n"; +#endif + + s += TRANSLATE("* Parts of the STUN project at http://sourceforge.net/projects/stun"); + if (html) s += "
"; + s += "\n"; + + s += TRANSLATE("* Parts of libsrv at http://libsrv.sourceforge.net/"); + if (html) s += "
"; + s += "\n"; + + if (html) s += "
"; + s += "\n"; + + s += TRANSLATE("For RTP the following dynamic libraries are linked:"); + if (html) s += "
"; + s += "\n"; + + s += "* GNU ccRTP - http://www.gnu.org/software/ccrtp"; + if (html) s += "
"; + s += "\n"; + + s += "* GNU CommonC++ - http://www.gnu.org/software/commoncpp"; + if (html) s += "

"; + s += "\n\n"; + + // Display information about translator only on non-english version. + string translated_by = TRANSLATE("Translated to english by "); + if (translated_by != "Translated to english by ") { + s += translated_by; + if (html) s += "

"; + s += "\n\n"; + } + + s += PRODUCT_NAME; + s += " comes with ABSOLUTELY NO WARRANTY."; + if (html) s += "
"; + s += "\n"; + + s += "This program is free software; you can redistribute it and/or modify"; + if (html) s += "
"; + s += "\n"; + + s += "it under the terms of the GNU General Public License as published by"; + if (html) s += "
"; + s += "\n"; + + s += "the Free Software Foundation; either version 2 of the License, or"; + if (html) s += "
"; + s += "\n"; + + s += "(at your option) any later version."; + if (html) s += "
"; + s += "\n"; + + return s; +} + +string t_sys_settings::get_product_date(void) const { + struct tm t; + t.tm_sec = 0; + t.tm_min = 0; + t.tm_hour = 0; + + vector l = split(PRODUCT_DATE, ' '); + assert(l.size() == 3); + t.tm_mon = str2month_full(l[0]); + t.tm_mday = atoi(l[1].c_str()); + t.tm_year = atoi(l[2].c_str()) - 1900; + + char buf[64]; + strftime(buf, 64, "%d %B %Y", &t); + return string(buf); +} + +string t_sys_settings::get_options_built(void) const { + string options_built; +#ifdef HAVE_LIBASOUND + if (!options_built.empty()) options_built += ", "; + options_built += "ALSA"; +#endif +#ifdef HAVE_KDE + if (!options_built.empty()) options_built += ", "; + options_built += "KDE"; +#endif +#ifdef HAVE_SPEEX + if (!options_built.empty()) options_built += ", "; + options_built += "Speex"; +#endif +#ifdef HAVE_ILBC + if (!options_built.empty()) options_built += ", "; + options_built += "iLBC"; +#endif +#ifdef HAVE_ZRTP + if (!options_built.empty()) options_built += ", "; + options_built += "ZRTP"; +#endif + + return options_built; +} + +bool t_sys_settings::check_environment(string &error_msg) const { + struct stat stat_buf; + string filename, dirname; + + mtx_sys.lock(); + + // Check if share directory exists + if (stat(dir_share.c_str(), &stat_buf) != 0) { + error_msg = TRANSLATE("Directory %1 does not exist."); + error_msg = replace_first(error_msg, "%1", dir_share); + mtx_sys.unlock(); + return false; + } + + // Check if audio file for ring tone exist + filename = dir_share; + filename += '/'; + filename += FILE_RINGTONE; + ifstream f_ringtone(filename.c_str()); + if (!f_ringtone) { + error_msg = TRANSLATE("Cannot open file %1 ."); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + // Check if audio file for ring back exist + filename = dir_share; + filename += '/'; + filename += FILE_RINGBACK; + ifstream f_ringback(filename.c_str()); + if (!f_ringback) { + error_msg = TRANSLATE("Cannot open file %1 ."); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + // Check if $HOME is set correctly + if (string(DIR_HOME) == "") { + error_msg = TRANSLATE("%1 is not set to your home directory."); + error_msg = replace_first(error_msg, "%1", "$HOME"); + mtx_sys.unlock(); + return false; + } + if (stat(DIR_HOME, &stat_buf) != 0) { + error_msg = TRANSLATE("Directory %1 (%2) does not exist."); + error_msg = replace_first(error_msg, "%1", DIR_HOME); + error_msg = replace_first(error_msg, "%2", "$HOME"); + mtx_sys.unlock(); + return false; + } + + // Check if user directory exists + dirname = get_dir_user(); + if (stat(dirname.c_str(), &stat_buf) != 0) { + // User directory does not exist. Create it now. + if (mkdir(dirname.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + // Failed to create the user directory + error_msg = TRANSLATE("Cannot create directory %1 ."); + error_msg = replace_first(error_msg, "%1", dirname); + mtx_sys.unlock(); + return false; + } + } + + // Check if tmp file directory exists + dirname = get_dir_tmpfile(); + if (stat(dirname.c_str(), &stat_buf) != 0) { + // Tmp file directory does not exist. Create it now. + if (mkdir(dirname.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + // Failed to create the tmp file directory + error_msg = TRANSLATE("Cannot create directory %1 ."); + error_msg = replace_first(error_msg, "%1", dirname); + mtx_sys.unlock(); + return false; + } + } + + mtx_sys.unlock(); + return true; +} + +void t_sys_settings::set_dir_share(const string &dir) { + mtx_sys.lock(); + dir_share = dir; + mtx_sys.unlock(); +} + +string t_sys_settings::get_dir_share(void) const { + string result; + mtx_sys.lock(); + result = dir_share; + mtx_sys.unlock(); + return result; +} + +string t_sys_settings::get_dir_lang(void) const { + string result = get_dir_share(); + result += "/lang"; + return result; +} + +string t_sys_settings::get_dir_user(void) const { + string dir = DIR_HOME; + dir += "/"; + dir += DIR_USER; + + return dir; +} + +string t_sys_settings::get_history_file(void) const { + string dir = get_dir_user(); + dir += "/"; + dir += FILE_CLI_HISTORY; + + return dir; +} + +string t_sys_settings::get_dir_tmpfile(void) const { + string dir = get_dir_user(); + dir += "/"; + dir += DIR_TMPFILE; + + return dir; +} + +bool t_sys_settings::is_tmpfile(const string &filename) const { + string tmpdir = get_dir_tmpfile(); + + return filename.substr(0, tmpdir.size()) == tmpdir; +} + +bool t_sys_settings::save_tmp_file(const string &data, const string &file_extension, + string &filename, string &error_msg) +{ + string fname = get_dir_tmpfile(); + fname += "/XXXXXX"; + + char *tmpfile = strdup(fname.c_str()); + MEMMAN_NEW(tmpfile); + int fd = mkstemp(tmpfile); + + if (fd < 0) { + error_msg = get_error_str(errno); + MEMMAN_DELETE(tmpfile); + free(tmpfile); + return false; + } + + close(fd); + ofstream f(tmpfile); + if (!f) { + error_msg = TRANSLATE("Failed to create file %1"); + error_msg = replace_first(error_msg, "%1", tmpfile); + MEMMAN_DELETE(tmpfile); + free(tmpfile); + return false; + } + + f.write(data.c_str(), data.size()); + if (!f.good()) { + error_msg = TRANSLATE("Failed to write data to file %1"); + error_msg = replace_first(error_msg, "%1", tmpfile); + f.close(); + MEMMAN_DELETE(tmpfile); + free(tmpfile); + return false; + } + + f.close(); + + // Rename to name with extension + filename = apply_glob_to_filename(tmpfile, file_extension); + + if (rename(tmpfile, filename.c_str()) < 0) { + error_msg = get_error_str(errno); + MEMMAN_DELETE(tmpfile); + free(tmpfile); + return false; + } + + MEMMAN_DELETE(tmpfile); + free(tmpfile); + return true; +} + +bool t_sys_settings::save_sip_body(const t_sip_message &sip_msg, + const string &suggested_file_extension, + string &tmpname, string &save_as_name, string &error_msg) +{ + bool retval = true; + + if (!sip_msg.body) { + error_msg = "Missing body"; + return false; + } + + // Determine file extension and save-as name + // The algorithm to get the file extension (glob expression) is: + // 1) If the a file name is supplied in the Content-Disposition header, then + // take the file extension from that file name. + // 2) If no extension is found, then take the suggested_file_extension + // 3) If still no file extension is found, then retrieve the file extension + // from the t_media object in the Content-Type header. + string file_ext = suggested_file_extension; + save_as_name.clear(); + + if (sip_msg.hdr_content_disp.is_populated() && + sip_msg.hdr_content_disp.type == DISPOSITION_ATTACHMENT && + !sip_msg.hdr_content_disp.filename.empty()) + { + string x = get_extension_from_filename(sip_msg.hdr_content_disp.filename); + if (!x.empty()) file_ext = string("*." + x); + + save_as_name = strip_path_from_filename(sip_msg.hdr_content_disp.filename); + } + if (file_ext.empty()) { + file_ext = sip_msg.hdr_content_type.media.get_file_glob(); + + if (file_ext.empty()) { + file_ext = "*"; + } + } + + // Avoid copy of opaque data + if (sip_msg.body->get_type() == BODY_OPAQUE) { + t_sip_body_opaque *body_opaque = dynamic_cast(sip_msg.body); + retval = save_tmp_file(body_opaque->opaque, file_ext, tmpname, error_msg); + } else { + retval = save_tmp_file(sip_msg.body->encode(), file_ext, tmpname, error_msg); + } + + return retval; +} + +void t_sys_settings::remove_all_tmp_files(void) const { + DIR *tmpdir = opendir(get_dir_tmpfile().c_str()); + + if (!tmpdir) { + log_file->write_report(get_error_str(errno), "t_sys_settings::remove_all_tmp_files"); + return; + } + + struct dirent *entry = readdir(tmpdir); + while (entry) { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + string fname = get_dir_tmpfile(); + fname += PATH_SEPARATOR; + fname += entry->d_name; + + log_file->write_header("t_sys_settings::remove_all_tmp_files"); + log_file->write_raw("Remove tmp file "); + log_file->write_raw(fname); + log_file->write_endl(); + log_file->write_footer(); + + unlink(fname.c_str()); + } + + entry = readdir(tmpdir); + } + + closedir(tmpdir); +} + +bool t_sys_settings::create_lock_file(bool shared_lock, string &error_msg, + bool &already_running) +{ + string lck_filename; + already_running = false; + + lck_filename = DIR_HOME; + lck_filename += "/"; + lck_filename += DIR_USER; + lck_filename += "/"; + lck_filename += LOCK_FILENAME; + + fd_lock_file = open(lck_filename.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd_lock_file < 0) { + error_msg = TRANSLATE("Cannot create %1 ."); + error_msg = replace_first(error_msg, "%1", lck_filename); + error_msg += "\n"; + error_msg += get_error_str(errno); + return false; + } + + struct flock lock_options; + + // Try to acquire an exclusive lock + if (!shared_lock) + { + memset(&lock_options, 0, sizeof(struct flock)); + lock_options.l_type = F_WRLCK; + lock_options.l_whence = SEEK_SET; + + if (fcntl(fd_lock_file, F_SETLK, &lock_options) < 0) { + already_running = true; + error_msg = TRANSLATE("%1 is already running.\nLock file %2 already exists."); + error_msg = replace_first(error_msg, "%1", PRODUCT_NAME); + error_msg = replace_first(error_msg, "%2", lck_filename); + return false; + } + } + + // Convert the lock to a shared lock. If the user forces multiple + // instances of Twinkle to run, then each will have a shared lock. + memset(&lock_options, 0, sizeof(struct flock)); + lock_options.l_type = F_RDLCK; + lock_options.l_whence = SEEK_SET; + + if (fcntl(fd_lock_file, F_SETLK, &lock_options) < 0) { + error_msg = TRANSLATE("Cannot lock %1 ."); + error_msg = replace_first(error_msg, "%1", lck_filename); + return false; + } + + return true; +} + +void t_sys_settings::delete_lock_file(void) { + if (fd_lock_file >= 0) + { + struct flock lock_options; + lock_options.l_type = F_UNLCK; + lock_options.l_whence = SEEK_SET; + + fcntl(fd_lock_file, F_SETLK, &lock_options); + + close(fd_lock_file); + fd_lock_file = -1; + } +} + +bool t_sys_settings::read_config(string &error_msg) { + struct stat stat_buf; + + mtx_sys.lock(); + + // Check if config file exists + if (stat(filename.c_str(), &stat_buf) != 0) { + mtx_sys.unlock(); + return true; + } + + // Open config file + ifstream config(filename.c_str()); + if (!config) { + error_msg = TRANSLATE("Cannot open file for reading: %1"); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + // Read and parse config file. + while (!config.eof()) { + string line; + getline(config, line); + + // Check if read operation succeeded + if (!config.good() && !config.eof()) { + error_msg = TRANSLATE("File system error while reading file %1 ."); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + line = trim(line); + + // Skip empty lines + if (line.size() == 0) continue; + + // Skip comment lines + if (line[0] == '#') continue; + + vector l = split_on_first(line, '='); + if (l.size() != 2) { + error_msg = TRANSLATE("Syntax error in file %1 ."); + error_msg = replace_first(error_msg, "%1", filename); + error_msg += "\n"; + error_msg += line; + mtx_sys.unlock(); + return false; + } + + string parameter = trim(l[0]); + string value = trim(l[1]); + + if (parameter == FLD_DEV_RINGTONE) { + dev_ringtone = audio_device(value); + } else if (parameter == FLD_DEV_SPEAKER) { + dev_speaker = audio_device(value); + } else if (parameter == FLD_DEV_MIC) { + dev_mic = audio_device(value); + } else if (parameter == FLD_VALIDATE_AUDIO_DEV) { + validate_audio_dev = yesno2bool(value); + } else if (parameter == FLD_ALSA_PLAY_PERIOD_SIZE) { + alsa_play_period_size = atoi(value.c_str()); + } else if (parameter == FLD_ALSA_CAPTURE_PERIOD_SIZE) { + alsa_capture_period_size = atoi(value.c_str()); + } else if (parameter == FLD_OSS_FRAGMENT_SIZE) { + oss_fragment_size = atoi(value.c_str()); + } else if (parameter == FLD_LOG_MAX_SIZE) { + log_max_size = atoi(value.c_str()); + } else if (parameter == FLD_LOG_SHOW_SIP) { + log_show_sip = yesno2bool(value); + } else if (parameter == FLD_LOG_SHOW_STUN) { + log_show_stun = yesno2bool(value); + } else if (parameter == FLD_LOG_SHOW_MEMORY) { + log_show_memory = yesno2bool(value); + } else if (parameter == FLD_LOG_SHOW_DEBUG) { + log_show_debug = yesno2bool(value); + } else if (parameter == FLD_GUI_USE_SYSTRAY) { + gui_use_systray = yesno2bool(value); + } else if (parameter == FLD_GUI_HIDE_ON_CLOSE) { + gui_hide_on_close = yesno2bool(value); + } else if (parameter == FLD_GUI_AUTO_SHOW_INCOMING) { + gui_auto_show_incoming = yesno2bool(value); + } else if (parameter == FLD_GUI_AUTO_SHOW_TIMEOUT) { + gui_auto_show_timeout = atoi(value.c_str()); + } else if (parameter == FLD_GUI_BROWSER_CMD) { + gui_browser_cmd = value; + } else if (parameter == FLD_AB_SHOW_SIP_ONLY) { + ab_show_sip_only = yesno2bool(value); + } else if (parameter == FLD_AB_LOOKUP_NAME) { + ab_lookup_name = yesno2bool(value); + } else if (parameter == FLD_AB_OVERRIDE_DISPLAY) { + ab_override_display = yesno2bool(value); + } else if (parameter == FLD_AB_LOOKUP_PHOTO) { + ab_lookup_photo = yesno2bool(value); + } else if (parameter == FLD_CH_MAX_SIZE) { + ch_max_size = atoi(value.c_str()); + } else if (parameter == FLD_CALL_WAITING) { + call_waiting = yesno2bool(value); + } else if (parameter == FLD_HANGUP_BOTH_3WAY) { + hangup_both_3way = yesno2bool(value); + } else if (parameter == FLD_START_USER_PROFILE) { + if (!value.empty()) start_user_profiles.push_back(value); + } else if (parameter == FLD_START_HIDDEN) { + start_hidden = yesno2bool(value); + } else if (parameter == FLD_sip_udp_port) { // Deprecated parameter + config_sip_port = atoi(value.c_str()); + } else if (parameter == FLD_sip_port) { + config_sip_port = atoi(value.c_str()); + } else if (parameter == FLD_RTP_PORT) { + rtp_port = atoi(value.c_str()); + } else if (parameter == FLD_SIP_MAX_UDP_SIZE) { + sip_max_udp_size = atoi(value.c_str()); + } else if (parameter == FLD_SIP_MAX_TCP_SIZE) { + sip_max_tcp_size = atoi(value.c_str()); + } else if (parameter == FLD_PLAY_RINGTONE) { + play_ringtone = yesno2bool(value); + } else if (parameter == FLD_RINGTONE_FILE) { + ringtone_file = value; + } else if (parameter == FLD_PLAY_RINGBACK) { + play_ringback = yesno2bool(value); + } else if (parameter == FLD_RINGBACK_FILE) { + ringback_file = value; + } else if (parameter == FLD_LAST_USED_PROFILE) { + last_used_profile = value; + } else if (parameter == FLD_REDIAL_URL) { + redial_url.set_url(value); + if (!redial_url.is_valid()) { + redial_url.set_url(""); + } + } else if (parameter == FLD_REDIAL_DISPLAY) { + redial_display = value; + } else if (parameter == FLD_REDIAL_SUBJECT) { + redial_subject = value; + } else if (parameter == FLD_REDIAL_PROFILE) { + redial_profile = value; + } else if (parameter == FLD_REDIAL_HIDE_USER) { + redial_hide_user = yesno2bool(value); + } else if (parameter == FLD_DIAL_HISTORY) { + dial_history.push_back(value); + } else if (parameter == FLD_SHOW_DISPLAY) { + show_display = yesno2bool(value); + } else if (parameter == FLD_COMPACT_LINE_STATUS) { + //compact_line_status = yesno2bool(value); + } else if (parameter == FLD_SHOW_BUDDY_LIST) { + show_buddy_list = yesno2bool(value); + } else if (parameter == FLD_UI_SESSION_ID) { + ui_session_id = value; + } else if (parameter == FLD_UI_SESSION_ACTIVE_PROFILE) { + ui_session_active_profiles.push_back(value); + } else if (parameter == FLD_UI_SESSION_MAIN_GEOMETRY) { + ui_session_main_geometry = value; + } else if (parameter == FLD_UI_SESSION_MAIN_HIDDEN) { + ui_session_main_hidden = yesno2bool(value); + } else if (parameter == FLD_UI_SESSION_MAIN_STATE) { + ui_session_main_state = atoi(value.c_str()); + } else if (parameter == FLD_WARN_HIDE_USER) { + warn_hide_user = yesno2bool(value); + } else if (parameter == FLD_MIME_SHARED_DATABASE) { + mime_shared_database = value; + } + + // Unknown field names are skipped. + } + + mtx_sys.unlock(); + return true; +} + +bool t_sys_settings::write_config(string &error_msg) { + struct stat stat_buf; + + mtx_sys.lock(); + + // Make a backup of the file if we are editing an existing file, so + // that can be restored when writing fails. + string f_backup = filename + '~'; + if (stat(filename.c_str(), &stat_buf) == 0) { + if (rename(filename.c_str(), f_backup.c_str()) != 0) { + string err = get_error_str(errno); + error_msg = TRANSLATE("Failed to backup %1 to %2"); + error_msg = replace_first(error_msg, "%1", filename); + error_msg = replace_first(error_msg, "%2", f_backup); + error_msg += "\n"; + error_msg += err; + mtx_sys.unlock(); + return false; + } + } + + // Open file + ofstream config(filename.c_str()); + if (!config) { + error_msg = TRANSLATE("Cannot open file for writing: %1"); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + // Write AUDIO settings + config << "# AUDIO\n"; + config << FLD_DEV_RINGTONE << '=' << dev_ringtone.get_settings_value() << endl; + config << FLD_DEV_SPEAKER << '=' << dev_speaker.get_settings_value() << endl; + config << FLD_DEV_MIC << '=' << dev_mic.get_settings_value() << endl; + config << FLD_VALIDATE_AUDIO_DEV << '=' << bool2yesno(validate_audio_dev) << endl; + config << FLD_ALSA_PLAY_PERIOD_SIZE << '=' << alsa_play_period_size << endl; + config << FLD_ALSA_CAPTURE_PERIOD_SIZE << '=' << alsa_capture_period_size << endl; + config << FLD_OSS_FRAGMENT_SIZE << '=' << oss_fragment_size << endl; + config << endl; + + // Write LOG settings + config << "# LOG\n"; + config << FLD_LOG_MAX_SIZE << '=' << log_max_size << endl; + config << FLD_LOG_SHOW_SIP << '=' << bool2yesno(log_show_sip) << endl; + config << FLD_LOG_SHOW_STUN << '=' << bool2yesno(log_show_stun) << endl; + config << FLD_LOG_SHOW_MEMORY << '=' << bool2yesno(log_show_memory) << endl; + config << FLD_LOG_SHOW_DEBUG << '=' << bool2yesno(log_show_debug) << endl; + config << endl; + + // Write GUI settings + config << "# GUI\n"; + config << FLD_GUI_USE_SYSTRAY << '=' << bool2yesno(gui_use_systray) << endl; + config << FLD_GUI_HIDE_ON_CLOSE << '=' << bool2yesno(gui_hide_on_close) << endl; + config << FLD_GUI_AUTO_SHOW_INCOMING << '=' << bool2yesno(gui_auto_show_incoming) << endl; + config << FLD_GUI_AUTO_SHOW_TIMEOUT << '=' << gui_auto_show_timeout << endl; + config << FLD_GUI_BROWSER_CMD << '=' << gui_browser_cmd << endl; + config << endl; + + // Write address book settings + config << "# Address book\n"; + config << FLD_AB_SHOW_SIP_ONLY << '=' << bool2yesno(ab_show_sip_only) << endl; + config << FLD_AB_LOOKUP_NAME << '=' << bool2yesno(ab_lookup_name) << endl; + config << FLD_AB_OVERRIDE_DISPLAY << '=' << bool2yesno(ab_override_display) << endl; + config << FLD_AB_LOOKUP_PHOTO << '=' << bool2yesno(ab_lookup_photo) << endl; + config << endl; + + // Write call history settings + config << "# Call history\n"; + config << FLD_CH_MAX_SIZE << '=' << ch_max_size << endl; + config << endl; + + // Write service settings + config << "# Services\n"; + config << FLD_CALL_WAITING << '=' << bool2yesno(call_waiting) << endl; + config << FLD_HANGUP_BOTH_3WAY << '=' << bool2yesno(hangup_both_3way) << endl; + config << endl; + + // Write startup settings + config << "# Startup\n"; + + for (list::iterator i = start_user_profiles.begin(); + i != start_user_profiles.end(); i++) + { + config << FLD_START_USER_PROFILE << '=' << *i << endl; + } + + config << FLD_START_HIDDEN << '=' << bool2yesno(start_hidden) << endl; + config << endl; + + // Write network settings + config << "# Network\n"; + config << FLD_sip_port << '=' << config_sip_port << endl; + config << FLD_RTP_PORT << '=' << rtp_port << endl; + config << FLD_SIP_MAX_UDP_SIZE << '=' << sip_max_udp_size << endl; + config << FLD_SIP_MAX_TCP_SIZE << '=' << sip_max_tcp_size << endl; + config << endl; + + // Write ring tone settings + config << "# Ring tones\n"; + config << FLD_PLAY_RINGTONE << '=' << bool2yesno(play_ringtone) << endl; + config << FLD_RINGTONE_FILE << '=' << ringtone_file << endl; + config << FLD_PLAY_RINGBACK << '=' << bool2yesno(play_ringback) << endl; + config << FLD_RINGBACK_FILE << '=' << ringback_file << endl; + config << endl; + + // Write MIME settings + config << "# MIME settings\n"; + config << FLD_MIME_SHARED_DATABASE << '=' << mime_shared_database << endl; + config << endl; + + // Write persistent user interface state + config << "# Persistent user interface state\n"; + config << FLD_LAST_USED_PROFILE << '=' << last_used_profile << endl; + config << FLD_REDIAL_URL << '=' << redial_url.encode() << endl; + config << FLD_REDIAL_DISPLAY << '=' << redial_display << endl; + config << FLD_REDIAL_SUBJECT << '=' << redial_subject << endl; + config << FLD_REDIAL_PROFILE << '=' << redial_profile << endl; + config << FLD_REDIAL_HIDE_USER << '=' << bool2yesno(redial_hide_user) << endl; + config << FLD_SHOW_DISPLAY << '=' << bool2yesno(show_display) << endl; + //config << FLD_COMPACT_LINE_STATUS << '=' << bool2yesno(compact_line_status) << endl; + config << FLD_SHOW_BUDDY_LIST << '=' << bool2yesno(show_buddy_list) << endl; + config << FLD_WARN_HIDE_USER << '=' << bool2yesno(warn_hide_user) << endl; + + for (list::iterator i = dial_history.begin(); + i != dial_history.end(); i++) + { + config << FLD_DIAL_HISTORY << '=' << *i << endl; + } + + config << endl; + + // Write session settins + config << "# UI session settings\n"; + config << FLD_UI_SESSION_ID << '=' << ui_session_id << endl; + + for (list::iterator i = ui_session_active_profiles.begin(); + i != ui_session_active_profiles.end(); i++) + { + config << FLD_UI_SESSION_ACTIVE_PROFILE << '=' << *i << endl; + } + + config << FLD_UI_SESSION_MAIN_GEOMETRY << '=' << ui_session_main_geometry.encode() << endl; + config << FLD_UI_SESSION_MAIN_HIDDEN << '=' << bool2yesno(ui_session_main_hidden) << endl; + config << FLD_UI_SESSION_MAIN_STATE << '=' << ui_session_main_state << endl; + + config << endl; + + // Check if writing succeeded + if (!config.good()) { + // Restore backup + config.close(); + rename(f_backup.c_str(), filename.c_str()); + + error_msg = TRANSLATE("File system error while writing file %1 ."); + error_msg = replace_first(error_msg, "%1", filename); + mtx_sys.unlock(); + return false; + } + + mtx_sys.unlock(); + return true; +} + +list t_sys_settings::get_oss_devices(bool playback) const { + struct stat stat_buf; + list l; + + for (int i = -1; i <= 15; i ++) { + string dev = "/dev/dsp"; + if (i >= 0) dev += int2str(i); + t_audio_device oss_dev; + oss_dev.type = t_audio_device::OSS; + + // Check if device exists + if (stat(dev.c_str(), &stat_buf) != 0) continue; + + oss_dev.device = dev; + + // Get sound card name + int fd; + + if (playback) { + fd = open(dev.c_str(), O_WRONLY | O_NONBLOCK); + } else { + fd = open(dev.c_str(), O_RDONLY | O_NONBLOCK); + } + + if (fd >= 0) { + struct mixer_info soundcard_info; + if (ioctl(fd, SOUND_MIXER_INFO, &soundcard_info) != -1) { + oss_dev.name = ""; + oss_dev.name += soundcard_info.name; + oss_dev.name += " ("; + oss_dev.name += soundcard_info.id; + oss_dev.name += ")"; + } + + close(fd); + } else { + if (errno == EBUSY) { + oss_dev.name = TRANSLATE("unknown name (device is busy)"); + } else { + // Device is not available. + continue; + } + } + + // Check if the device is a symbolic link + char buf[32]; + int len_link; + if ((len_link = readlink(dev.c_str(), buf, 31)) != -1) { + buf[len_link] = 0; + oss_dev.sym_link = buf; + } + oss_dev.type = t_audio_device::OSS; + l.push_back(oss_dev); + } + + // If no OSS devices can be found (this should not happen), then + // just add /dev/dsp as the default device. + if (l.empty()) { + t_audio_device oss_dev; + oss_dev.device = "/dev/dsp"; + oss_dev.type = t_audio_device::OSS; + l.push_back(oss_dev); + } + + // Add other device option + t_audio_device other_dev; + other_dev.device = DEV_OTHER; + other_dev.type = t_audio_device::OSS; + l.push_back(other_dev); + + return l; +} + +#ifdef HAVE_LIBASOUND +// Defined in audio_device.cpp +void alsa_fill_soundcards(list& l, bool playback); + +list t_sys_settings::get_alsa_devices(bool playback) const { + t_audio_device defaultDevice; + defaultDevice.device = "default"; + defaultDevice.name = TRANSLATE("Default device"); + defaultDevice.type = t_audio_device::ALSA; + list l; + l.push_back(defaultDevice); + + alsa_fill_soundcards(l, playback); + + // Add other device option + t_audio_device other_dev; + other_dev.device = DEV_OTHER; + other_dev.type = t_audio_device::ALSA; + l.push_back(other_dev); + + return l; +} +#endif + +list t_sys_settings::get_audio_devices(bool playback) const { + list d, d0; + +#ifdef HAVE_LIBASOUND + d = get_alsa_devices(playback); +#endif + d0 = get_oss_devices(playback); + d.insert(d.end(), d0.begin(), d0.end()); + return d; +} + +bool t_sys_settings::equal_audio_dev(const t_audio_device &dev1, const t_audio_device &dev2) const { + if (dev1.type == t_audio_device::OSS) { + if (dev2.type != t_audio_device::OSS) return false; + if (dev1.device == dev2.device) return true; + + char symlink1[32], symlink2[32]; + int len_link1, len_link2; + + len_link1 = readlink(dev1.device.c_str(), symlink1, 31); + len_link2 = readlink(dev2.device.c_str(), symlink2, 31); + + if (len_link1 > 0) { + symlink1[len_link1] = 0; + string symdev1 = "/dev/"; + symdev1 += symlink1; + if (len_link2 > 0) { + symlink2[len_link2] = 0; + string symdev2 = "/dev/"; + symdev2 += symlink2; + return symdev1 == symdev2; + } else { + return dev2.device == symdev1; + } + } else { + if (len_link2 > 0) { + symlink2[len_link2] = 0; + string symdev2 = "/dev/"; + symdev2 += symlink2; + return dev1.device == symdev2; + } + } + } else if (dev1.type == t_audio_device::ALSA) { + if (dev2.type != t_audio_device::ALSA) return false; + return dev1.device == dev2.device; + } + + return false; +} + + +t_audio_device t_sys_settings::audio_device(string device) { + t_audio_device d; + + if (device.empty()) device = DEV_DSP; //This is the default device + + if (device.substr(0, strlen(PFX_OSS)) == PFX_OSS) { + // OSS device + d.device = device.substr(strlen(PFX_OSS)); + d.type = t_audio_device::OSS; + d.name = ""; + char symlink[32]; + int len_link = readlink(device.c_str(), symlink, 31); + if(len_link > 0) { + d.sym_link = symlink; + } + } else if (device.substr(0, strlen(PFX_ALSA)) == PFX_ALSA) { + // ALSA device + d.device = device.substr(strlen(PFX_ALSA)); + d.type = t_audio_device::ALSA; + d.name = ""; + d.sym_link = ""; + } else { + // Assume it is an OSS device. Version 0.2.1 and lower + // only supported OSS and the value only consisted of + // the device name without "oss:" + d.device = device; + d.type = t_audio_device::OSS; + d.name = ""; + char symlink[32]; + int len_link = readlink(device.c_str(), symlink, 31); + if(len_link > 0) { + d.sym_link = symlink; + } + } + + return d; +} + +bool t_sys_settings::exec_audio_validation(bool ringtone, bool speaker, bool mic, + string &error_msg) const +{ + error_msg.clear(); + if (!validate_audio_dev) return true; + + bool valid = true; + bool full_duplex = speaker && mic && equal_audio_dev(dev_speaker, dev_mic); + + if (ringtone && !t_audio_io::validate(dev_ringtone, true, false)) { + string msg = TRANSLATE("Cannot access the ring tone device (%1)."); + error_msg += replace_first(msg, "%1", dev_ringtone.get_description()); + error_msg += "\n"; + valid = false; + } + if (speaker && !t_audio_io::validate(dev_speaker, true, full_duplex)) { + string msg = TRANSLATE("Cannot access the speaker (%1)."); + error_msg += replace_first(msg, "%1", dev_speaker.get_description()); + error_msg += "\n"; + valid = false; + } + if (mic && !t_audio_io::validate(dev_mic, full_duplex, true)) { + string msg = TRANSLATE("Cannot access the microphone (%1)."); + error_msg += replace_first(msg, "%1", dev_mic.get_description()); + error_msg += "\n"; + valid = false; + } + + return valid; +} + +unsigned short t_sys_settings::get_sip_port(bool force_active) { + mtx_sys.lock(); + + // The configured port becomes the active port after first + // usage of the port. + if (!active_sip_port || force_active) { + if (override_sip_port > 0) { + // The port provided on the command line overrides + // the configured port. + active_sip_port = override_sip_port; + } else { + active_sip_port = config_sip_port; + } + } + + mtx_sys.unlock(); + return active_sip_port; +} -- cgit v1.2.3