LCOV - code coverage report
Current view: top level - foo/src - preferences.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 243 275 88.4 %
Date: 2026-02-28 10:41:24 Functions: 23 25 92.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifdef HAVE_CONFIG_H
      19             : #include "config.h"
      20             : #endif
      21             : 
      22             : #include "preferences.h"
      23             : #include "logger.h"
      24             : #include "audio/audiolayer.h"
      25             : 
      26             : #if HAVE_AAUDIO
      27             : #include "audio/aaudio/aaudiolayer.h"
      28             : #else
      29             : #if HAVE_ALSA
      30             : #include "audio/alsa/alsalayer.h"
      31             : #endif
      32             : #if HAVE_JACK
      33             : #include "audio/jack/jacklayer.h"
      34             : #endif
      35             : #if HAVE_PULSE
      36             : #include "audio/pulseaudio/pulselayer.h"
      37             : #endif
      38             : #if HAVE_COREAUDIO
      39             : #ifdef __APPLE__
      40             : #include <TargetConditionals.h>
      41             : #endif
      42             : #if TARGET_OS_IOS
      43             : #include "audio/coreaudio/ios/corelayer.h"
      44             : #else
      45             : #include "audio/coreaudio/osx/corelayer.h"
      46             : #endif /* TARGET_OS_IOS */
      47             : #endif /* HAVE_COREAUDIO */
      48             : #if HAVE_PORTAUDIO
      49             : #include "audio/portaudio/portaudiolayer.h"
      50             : #endif
      51             : #endif /* HAVE_AAUDIO */
      52             : 
      53             : #ifdef ENABLE_VIDEO
      54             : #include "client/videomanager.h"
      55             : #endif
      56             : 
      57             : #pragma GCC diagnostic push
      58             : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
      59             : #include <yaml-cpp/yaml.h>
      60             : #pragma GCC diagnostic pop
      61             : 
      62             : #include "config/yamlparser.h"
      63             : #include "connectivity/sip_utils.h"
      64             : #include <sstream>
      65             : #include <algorithm>
      66             : #include <stdexcept>
      67             : #include "fileutils.h"
      68             : #include "string_utils.h"
      69             : 
      70             : namespace jami {
      71             : 
      72             : using yaml_utils::parseValue;
      73             : 
      74             : constexpr const char* const Preferences::CONFIG_LABEL;
      75             : const char* const Preferences::DFT_ZONE = "North America";
      76             : const char* const Preferences::REGISTRATION_EXPIRE_KEY = "registrationexpire";
      77             : constexpr std::string_view DEFAULT_CONFERENCE_RESOLUTION {"1280x720"};
      78             : 
      79             : // general preferences
      80             : static constexpr const char* ORDER_KEY {"order"};
      81             : static constexpr const char* PENDING_ACCOUNTS_KEY {"pendingAccounts"};
      82             : static constexpr const char* AUDIO_API_KEY {"audioApi"};
      83             : static constexpr const char* HISTORY_LIMIT_KEY {"historyLimit"};
      84             : static constexpr const char* RINGING_TIMEOUT {"ringingTimeout"};
      85             : static constexpr const char* HISTORY_MAX_CALLS_KEY {"historyMaxCalls"};
      86             : static constexpr const char* ZONE_TONE_CHOICE_KEY {"zoneToneChoice"};
      87             : static constexpr const char* PORT_NUM_KEY {"portNum"};
      88             : static constexpr const char* SEARCH_BAR_DISPLAY_KEY {"searchBarDisplay"};
      89             : static constexpr const char* MD5_HASH_KEY {"md5Hash"};
      90             : 
      91             : // voip preferences
      92             : constexpr const char* const VoipPreference::CONFIG_LABEL;
      93             : static constexpr const char* PLAY_DTMF_KEY {"playDtmf"};
      94             : static constexpr const char* PLAY_TONES_KEY {"playTones"};
      95             : static constexpr const char* PULSE_LENGTH_KEY {"pulseLength"};
      96             : 
      97             : // audio preferences
      98             : constexpr const char* const AudioPreference::CONFIG_LABEL;
      99             : static constexpr const char* ALSAMAP_KEY {"alsa"};
     100             : static constexpr const char* PULSEMAP_KEY {"pulse"};
     101             : static constexpr const char* PORTAUDIO_KEY {"portaudio"};
     102             : static constexpr const char* CARDIN_KEY {"cardIn"};
     103             : static constexpr const char* CARDOUT_KEY {"cardOut"};
     104             : static constexpr const char* CARLIBJAMI_KEY {"cardRing"};
     105             : static constexpr const char* PLUGIN_KEY {"plugin"};
     106             : static constexpr const char* SMPLRATE_KEY {"smplRate"};
     107             : static constexpr const char* DEVICE_PLAYBACK_KEY {"devicePlayback"};
     108             : static constexpr const char* DEVICE_RECORD_KEY {"deviceRecord"};
     109             : static constexpr const char* DEVICE_RINGTONE_KEY {"deviceRingtone"};
     110             : static constexpr const char* RECORDPATH_KEY {"recordPath"};
     111             : static constexpr const char* ALWAYS_RECORDING_KEY {"alwaysRecording"};
     112             : static constexpr const char* VOLUMEMIC_KEY {"volumeMic"};
     113             : static constexpr const char* VOLUMESPKR_KEY {"volumeSpkr"};
     114             : static constexpr const char* AUDIO_PROCESSOR_KEY {"audioProcessor"};
     115             : static constexpr const char* NOISE_REDUCE_KEY {"noiseReduce"};
     116             : static constexpr const char* AGC_KEY {"automaticGainControl"};
     117             : static constexpr const char* CAPTURE_MUTED_KEY {"captureMuted"};
     118             : static constexpr const char* PLAYBACK_MUTED_KEY {"playbackMuted"};
     119             : static constexpr const char* VAD_KEY {"voiceActivityDetection"};
     120             : static constexpr const char* ECHO_CANCEL_KEY {"echoCancel"};
     121             : 
     122             : #ifdef ENABLE_VIDEO
     123             : // video preferences
     124             : constexpr const char* const VideoPreferences::CONFIG_LABEL;
     125             : static constexpr const char* DECODING_ACCELERATED_KEY {"decodingAccelerated"};
     126             : static constexpr const char* ENCODING_ACCELERATED_KEY {"encodingAccelerated"};
     127             : static constexpr const char* RECORD_PREVIEW_KEY {"recordPreview"};
     128             : static constexpr const char* RECORD_QUALITY_KEY {"recordQuality"};
     129             : static constexpr const char* CONFERENCE_RESOLUTION_KEY {"conferenceResolution"};
     130             : #endif
     131             : 
     132             : #ifdef ENABLE_PLUGIN
     133             : // plugin preferences
     134             : constexpr const char* const PluginPreferences::CONFIG_LABEL;
     135             : static constexpr const char* JAMI_PLUGIN_KEY {"pluginsEnabled"};
     136             : static constexpr const char* JAMI_PLUGINS_INSTALLED_KEY {"installedPlugins"};
     137             : static constexpr const char* JAMI_PLUGINS_LOADED_KEY {"loadedPlugins"};
     138             : #endif
     139             : 
     140             : static constexpr int PULSE_LENGTH_DEFAULT {250}; /** Default DTMF length */
     141             : #ifndef _MSC_VER
     142             : static constexpr const char* ALSA_DFT_CARD {"0"}; /** Default sound card index */
     143             : #else
     144             : static constexpr const char* ALSA_DFT_CARD {"-1"}; /** Default sound card index (Portaudio) */
     145             : #endif // _MSC_VER
     146             : 
     147          37 : Preferences::Preferences()
     148          37 :     : accountOrder_("")
     149          37 :     , historyLimit_(0)
     150          37 :     , historyMaxCalls_(20)
     151          37 :     , ringingTimeout_(30)
     152          37 :     , zoneToneChoice_(DFT_ZONE) // DFT_ZONE
     153          37 :     , portNum_(sip_utils::DEFAULT_SIP_PORT)
     154          37 :     , searchBarDisplay_(true)
     155          74 :     , md5Hash_(false)
     156          37 : {}
     157             : 
     158             : void
     159        2399 : Preferences::verifyAccountOrder(const std::vector<std::string>& accountIDs)
     160             : {
     161        2399 :     std::vector<std::string> tokens;
     162        2399 :     std::string token;
     163        2399 :     bool drop = false;
     164             : 
     165      105090 :     for (const auto c : accountOrder_) {
     166      102691 :         if (c != '/') {
     167       96788 :             token += c;
     168             :         } else {
     169        5903 :             if (find(accountIDs.begin(), accountIDs.end(), token) != accountIDs.end())
     170        5896 :                 tokens.push_back(token);
     171             :             else {
     172           7 :                 JAMI_DBG("Dropping nonexistent account %s", token.c_str());
     173           7 :                 drop = true;
     174             :             }
     175        5903 :             token.clear();
     176             :         }
     177             :     }
     178             : 
     179        2399 :     if (drop) {
     180           4 :         accountOrder_.clear();
     181           5 :         for (const auto& t : tokens)
     182           1 :             accountOrder_ += t + '/';
     183             :     }
     184        2399 : }
     185             : 
     186             : void
     187         781 : Preferences::addAccount(const std::string& newAccountID)
     188             : {
     189             :     // Add the newly created account in the account order list
     190         781 :     if (not accountOrder_.empty())
     191         529 :         accountOrder_.insert(0, newAccountID + "/");
     192             :     else
     193         252 :         accountOrder_ = newAccountID + "/";
     194         781 : }
     195             : 
     196             : void
     197         788 : Preferences::removeAccount(const std::string& oldAccountID)
     198             : {
     199             :     // include the slash since we don't want to remove a partial match
     200         788 :     const size_t start = accountOrder_.find(oldAccountID + "/");
     201         788 :     if (start != std::string::npos)
     202         781 :         accountOrder_.erase(start, oldAccountID.length() + 1);
     203         788 : }
     204             : 
     205             : bool
     206          37 : Preferences::isAccountPending(const std::string& accountId) const
     207             : {
     208          37 :     return pendingAccountIds_.count(accountId) > 0;
     209             : }
     210             : 
     211             : bool
     212         781 : Preferences::addPendingAccountId(const std::string& accountId)
     213             : {
     214         781 :     if (accountId.empty())
     215           0 :         return false;
     216         781 :     return pendingAccountIds_.insert(accountId).second;
     217             : }
     218             : 
     219             : bool
     220        1575 : Preferences::removePendingAccountId(const std::string& accountId)
     221             : {
     222        1575 :     if (accountId.empty())
     223           5 :         return false;
     224        1570 :     return pendingAccountIds_.erase(accountId) > 0;
     225             : }
     226             : 
     227             : void
     228        2399 : Preferences::serialize(YAML::Emitter& out) const
     229             : {
     230        2399 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     231             : 
     232        2399 :     out << YAML::Key << HISTORY_LIMIT_KEY << YAML::Value << historyLimit_;
     233        2399 :     out << YAML::Key << RINGING_TIMEOUT << YAML::Value << ringingTimeout_;
     234        2399 :     out << YAML::Key << HISTORY_MAX_CALLS_KEY << YAML::Value << historyMaxCalls_;
     235        2399 :     out << YAML::Key << MD5_HASH_KEY << YAML::Value << md5Hash_;
     236        2399 :     out << YAML::Key << ORDER_KEY << YAML::Value << accountOrder_;
     237        2399 :     out << YAML::Key << PORT_NUM_KEY << YAML::Value << portNum_;
     238        2399 :     out << YAML::Key << SEARCH_BAR_DISPLAY_KEY << YAML::Value << searchBarDisplay_;
     239        2399 :     out << YAML::Key << ZONE_TONE_CHOICE_KEY << YAML::Value << zoneToneChoice_;
     240        2399 :     out << YAML::Key << PENDING_ACCOUNTS_KEY << YAML::Value << YAML::BeginSeq;
     241        5268 :     for (const auto& accountId : pendingAccountIds_)
     242        2869 :         out << accountId;
     243        2399 :     out << YAML::EndSeq;
     244        2399 :     out << YAML::EndMap;
     245        2399 : }
     246             : 
     247             : void
     248          34 : Preferences::unserialize(const YAML::Node& in)
     249             : {
     250          34 :     const auto& node = in[CONFIG_LABEL];
     251             : 
     252          34 :     parseValue(node, ORDER_KEY, accountOrder_);
     253          28 :     parseValue(node, HISTORY_LIMIT_KEY, historyLimit_);
     254          28 :     parseValue(node, RINGING_TIMEOUT, ringingTimeout_);
     255          28 :     parseValue(node, HISTORY_MAX_CALLS_KEY, historyMaxCalls_);
     256          28 :     parseValue(node, ZONE_TONE_CHOICE_KEY, zoneToneChoice_);
     257          28 :     parseValue(node, PORT_NUM_KEY, portNum_);
     258          28 :     parseValue(node, SEARCH_BAR_DISPLAY_KEY, searchBarDisplay_);
     259          28 :     parseValue(node, MD5_HASH_KEY, md5Hash_);
     260             : 
     261          28 :     pendingAccountIds_.clear();
     262          28 :     if (const auto& pending = node[PENDING_ACCOUNTS_KEY]; pending && pending.IsSequence()) {
     263          31 :         for (const auto& entry : pending) {
     264             :             try {
     265           3 :                 pendingAccountIds_.insert(entry.as<std::string>());
     266           0 :             } catch (const YAML::Exception& e) {
     267           0 :                 JAMI_WARN("[config] Unable to read pending account id: %s", e.what());
     268           0 :             }
     269          31 :         }
     270          28 :     }
     271          34 : }
     272             : 
     273          37 : VoipPreference::VoipPreference()
     274          37 :     : playDtmf_(true)
     275          37 :     , playTones_(true)
     276          37 :     , pulseLength_(PULSE_LENGTH_DEFAULT)
     277          37 : {}
     278             : 
     279             : void
     280        2399 : VoipPreference::serialize(YAML::Emitter& out) const
     281             : {
     282        2399 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     283        2399 :     out << YAML::Key << PLAY_DTMF_KEY << YAML::Value << playDtmf_;
     284        2399 :     out << YAML::Key << PLAY_TONES_KEY << YAML::Value << playTones_;
     285        2399 :     out << YAML::Key << PULSE_LENGTH_KEY << YAML::Value << pulseLength_;
     286        2399 :     out << YAML::EndMap;
     287        2399 : }
     288             : 
     289             : void
     290          28 : VoipPreference::unserialize(const YAML::Node& in)
     291             : {
     292          28 :     const auto& node = in[CONFIG_LABEL];
     293          28 :     parseValue(node, PLAY_DTMF_KEY, playDtmf_);
     294          28 :     parseValue(node, PLAY_TONES_KEY, playTones_);
     295          28 :     parseValue(node, PULSE_LENGTH_KEY, pulseLength_);
     296          28 : }
     297             : 
     298          37 : AudioPreference::AudioPreference()
     299          37 :     : audioApi_(PULSEAUDIO_API_STR)
     300          37 :     , alsaCardin_(atoi(ALSA_DFT_CARD))
     301          37 :     , alsaCardout_(atoi(ALSA_DFT_CARD))
     302          37 :     , alsaCardRingtone_(atoi(ALSA_DFT_CARD))
     303          37 :     , alsaPlugin_("default")
     304          37 :     , alsaSmplrate_(44100)
     305          37 :     , pulseDevicePlayback_("")
     306          37 :     , pulseDeviceRecord_("")
     307          37 :     , pulseDeviceRingtone_("")
     308          37 :     , recordpath_("")
     309          37 :     , alwaysRecording_(false)
     310          37 :     , volumemic_(1.0)
     311          37 :     , volumespkr_(1.0)
     312          37 :     , audioProcessor_("webrtc")
     313          37 :     , denoise_("auto")
     314          37 :     , agcEnabled_(true)
     315          37 :     , vadEnabled_(true)
     316          37 :     , echoCanceller_("auto")
     317          37 :     , captureMuted_(false)
     318          74 :     , playbackMuted_(false)
     319          37 : {}
     320             : 
     321             : #if HAVE_ALSA
     322             : 
     323             : static const int ALSA_DFT_CARD_ID = 0; // Index of the default soundcard
     324             : 
     325             : static void
     326          93 : checkSoundCard(int& card, AudioDeviceType type)
     327             : {
     328          93 :     if (not AlsaLayer::soundCardIndexExists(card, type)) {
     329          93 :         JAMI_WARN(" Card with index %d doesn't exist or is unusable.", card);
     330          93 :         card = ALSA_DFT_CARD_ID;
     331             :     }
     332          93 : }
     333             : #endif
     334             : 
     335             : AudioLayer*
     336          31 : AudioPreference::createAudioLayer()
     337             : {
     338             : #if HAVE_AAUDIO
     339             :     return new AAudioLayer(*this);
     340             : #else
     341             : 
     342             : #if HAVE_JACK
     343             :     if (audioApi_ == JACK_API_STR) {
     344             :         try {
     345             :             if (auto ret = system("jack_lsp > /dev/null"))
     346             :                 throw std::runtime_error("Error running jack_lsp: " + std::to_string(ret));
     347             :             return new JackLayer(*this);
     348             :         } catch (const std::runtime_error& e) {
     349             :             JAMI_ERR("%s", e.what());
     350             : #if HAVE_PULSE
     351             :             audioApi_ = PULSEAUDIO_API_STR;
     352             : #elif HAVE_ALSA
     353             :             audioApi_ = ALSA_API_STR;
     354             : #elif HAVE_COREAUDIO
     355             :             audioApi_ = COREAUDIO_API_STR;
     356             : #elif HAVE_PORTAUDIO
     357             :             audioApi_ = PORTAUDIO_API_STR;
     358             : #else
     359             :             throw;
     360             : #endif // HAVE_PULSE
     361             :         }
     362             :     }
     363             : #endif // HAVE_JACK
     364             : 
     365             : #if HAVE_PULSE
     366             : 
     367          31 :     if (audioApi_ == PULSEAUDIO_API_STR) {
     368             :         try {
     369           3 :             return new PulseLayer(*this);
     370           3 :         } catch (const std::runtime_error& e) {
     371           3 :             JAMI_WARN("Unable to create pulseaudio layer, falling back to ALSA");
     372           3 :         }
     373             :     }
     374             : 
     375             : #endif
     376             : 
     377             : #if HAVE_ALSA
     378             : 
     379          31 :     audioApi_ = ALSA_API_STR;
     380          31 :     checkSoundCard(alsaCardin_, AudioDeviceType::CAPTURE);
     381          31 :     checkSoundCard(alsaCardout_, AudioDeviceType::PLAYBACK);
     382          31 :     checkSoundCard(alsaCardRingtone_, AudioDeviceType::RINGTONE);
     383             : 
     384          31 :     return new AlsaLayer(*this);
     385             : #endif
     386             : 
     387             : #if HAVE_COREAUDIO
     388             :     audioApi_ = COREAUDIO_API_STR;
     389             :     try {
     390             :         return new CoreLayer(*this);
     391             :     } catch (const std::runtime_error& e) {
     392             :         JAMI_WARN("Unable to create coreaudio layer. There will be no sound.");
     393             :     }
     394             :     return NULL;
     395             : #endif
     396             : 
     397             : #if HAVE_PORTAUDIO
     398             :     audioApi_ = PORTAUDIO_API_STR;
     399             :     try {
     400             :         return new PortAudioLayer(*this);
     401             :     } catch (const std::runtime_error& e) {
     402             :         JAMI_WARN("Unable to create PortAudio layer. There will be no sound.");
     403             :     }
     404             :     return nullptr;
     405             : #endif
     406             : #endif // HAVE_AAUDIO
     407             : 
     408             :     JAMI_WARN("No audio layer provided");
     409             :     return nullptr;
     410             : }
     411             : 
     412             : std::vector<std::string>
     413           0 : AudioPreference::getSupportedAudioManagers()
     414             : {
     415             :     return {
     416             : #if HAVE_AAUDIO
     417             :         AAUDIO_API_STR,
     418             : #endif
     419             : #if HAVE_ALSA
     420             :         ALSA_API_STR,
     421             : #endif
     422             : #if HAVE_PULSE
     423             :         PULSEAUDIO_API_STR,
     424             : #endif
     425             : #if HAVE_JACK
     426             :         JACK_API_STR,
     427             : #endif
     428             : #if HAVE_COREAUDIO
     429             :         COREAUDIO_API_STR,
     430             : #endif
     431             : #if HAVE_PORTAUDIO
     432             :         PORTAUDIO_API_STR,
     433             : #endif
     434           0 :     };
     435             : }
     436             : 
     437             : void
     438        2399 : AudioPreference::serialize(YAML::Emitter& out) const
     439             : {
     440        2399 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     441             :     // alsa submap
     442        2399 :     out << YAML::Key << ALSAMAP_KEY << YAML::Value << YAML::BeginMap;
     443        2399 :     out << YAML::Key << CARDIN_KEY << YAML::Value << alsaCardin_;
     444        2399 :     out << YAML::Key << CARDOUT_KEY << YAML::Value << alsaCardout_;
     445        2399 :     out << YAML::Key << CARLIBJAMI_KEY << YAML::Value << alsaCardRingtone_;
     446        2399 :     out << YAML::Key << PLUGIN_KEY << YAML::Value << alsaPlugin_;
     447        2399 :     out << YAML::Key << SMPLRATE_KEY << YAML::Value << alsaSmplrate_;
     448        2399 :     out << YAML::EndMap;
     449             : 
     450             :     // common options
     451        2399 :     out << YAML::Key << ALWAYS_RECORDING_KEY << YAML::Value << alwaysRecording_;
     452        2399 :     out << YAML::Key << AUDIO_API_KEY << YAML::Value << audioApi_;
     453        2399 :     out << YAML::Key << CAPTURE_MUTED_KEY << YAML::Value << captureMuted_;
     454        2399 :     out << YAML::Key << PLAYBACK_MUTED_KEY << YAML::Value << playbackMuted_;
     455             : 
     456             :     // pulse submap
     457        2399 :     out << YAML::Key << PULSEMAP_KEY << YAML::Value << YAML::BeginMap;
     458        2399 :     out << YAML::Key << DEVICE_PLAYBACK_KEY << YAML::Value << pulseDevicePlayback_;
     459        2399 :     out << YAML::Key << DEVICE_RECORD_KEY << YAML::Value << pulseDeviceRecord_;
     460        2399 :     out << YAML::Key << DEVICE_RINGTONE_KEY << YAML::Value << pulseDeviceRingtone_;
     461        2399 :     out << YAML::EndMap;
     462             : 
     463             :     // portaudio submap
     464        2399 :     out << YAML::Key << PORTAUDIO_KEY << YAML::Value << YAML::BeginMap;
     465        2399 :     out << YAML::Key << DEVICE_PLAYBACK_KEY << YAML::Value << portaudioDevicePlayback_;
     466        2399 :     out << YAML::Key << DEVICE_RECORD_KEY << YAML::Value << portaudioDeviceRecord_;
     467        2399 :     out << YAML::Key << DEVICE_RINGTONE_KEY << YAML::Value << portaudioDeviceRingtone_;
     468        2399 :     out << YAML::EndMap;
     469             : 
     470             :     // more common options!
     471        2399 :     out << YAML::Key << RECORDPATH_KEY << YAML::Value << recordpath_;
     472        2399 :     out << YAML::Key << VOLUMEMIC_KEY << YAML::Value << volumemic_;
     473        2399 :     out << YAML::Key << VOLUMESPKR_KEY << YAML::Value << volumespkr_;
     474             : 
     475             :     // audio processor options, not in a submap
     476        2399 :     out << YAML::Key << AUDIO_PROCESSOR_KEY << YAML::Value << audioProcessor_;
     477        2399 :     out << YAML::Key << AGC_KEY << YAML::Value << agcEnabled_;
     478        2399 :     out << YAML::Key << VAD_KEY << YAML::Value << vadEnabled_;
     479        2399 :     out << YAML::Key << NOISE_REDUCE_KEY << YAML::Value << denoise_;
     480        2399 :     out << YAML::Key << ECHO_CANCEL_KEY << YAML::Value << echoCanceller_;
     481        2399 :     out << YAML::EndMap;
     482        2399 : }
     483             : 
     484             : bool
     485           0 : AudioPreference::setRecordPath(const std::string& r)
     486             : {
     487           0 :     std::string path = fileutils::expand_path(r);
     488           0 :     if (fileutils::isDirectoryWritable(path)) {
     489           0 :         recordpath_ = path;
     490           0 :         return true;
     491             :     } else {
     492           0 :         JAMI_ERR("%s is not writable, unable to be the recording path", path.c_str());
     493           0 :         return false;
     494             :     }
     495           0 : }
     496             : 
     497             : void
     498          28 : AudioPreference::unserialize(const YAML::Node& in)
     499             : {
     500          28 :     const auto& node = in[CONFIG_LABEL];
     501             : 
     502             :     // alsa submap
     503          28 :     const auto& alsa = node[ALSAMAP_KEY];
     504             : 
     505          28 :     parseValue(alsa, CARDIN_KEY, alsaCardin_);
     506          28 :     parseValue(alsa, CARDOUT_KEY, alsaCardout_);
     507          28 :     parseValue(alsa, CARLIBJAMI_KEY, alsaCardRingtone_);
     508          28 :     parseValue(alsa, PLUGIN_KEY, alsaPlugin_);
     509          28 :     parseValue(alsa, SMPLRATE_KEY, alsaSmplrate_);
     510             : 
     511             :     // common options
     512          28 :     parseValue(node, ALWAYS_RECORDING_KEY, alwaysRecording_);
     513          28 :     parseValue(node, AUDIO_API_KEY, audioApi_);
     514          28 :     parseValue(node, AGC_KEY, agcEnabled_);
     515          28 :     parseValue(node, CAPTURE_MUTED_KEY, captureMuted_);
     516          28 :     parseValue(node, NOISE_REDUCE_KEY, denoise_);
     517          28 :     parseValue(node, PLAYBACK_MUTED_KEY, playbackMuted_);
     518             : 
     519             :     // pulse submap
     520          28 :     const auto& pulse = node[PULSEMAP_KEY];
     521          28 :     parseValue(pulse, DEVICE_PLAYBACK_KEY, pulseDevicePlayback_);
     522          28 :     parseValue(pulse, DEVICE_RECORD_KEY, pulseDeviceRecord_);
     523          28 :     parseValue(pulse, DEVICE_RINGTONE_KEY, pulseDeviceRingtone_);
     524             : 
     525             :     // portaudio submap
     526          28 :     const auto& portaudio = node[PORTAUDIO_KEY];
     527          28 :     parseValue(portaudio, DEVICE_PLAYBACK_KEY, portaudioDevicePlayback_);
     528          28 :     parseValue(portaudio, DEVICE_RECORD_KEY, portaudioDeviceRecord_);
     529          28 :     parseValue(portaudio, DEVICE_RINGTONE_KEY, portaudioDeviceRingtone_);
     530             : 
     531             :     // more common options!
     532          28 :     parseValue(node, RECORDPATH_KEY, recordpath_);
     533          28 :     parseValue(node, VOLUMEMIC_KEY, volumemic_);
     534          28 :     parseValue(node, VOLUMESPKR_KEY, volumespkr_);
     535          28 :     parseValue(node, AUDIO_PROCESSOR_KEY, audioProcessor_);
     536          28 :     parseValue(node, VAD_KEY, vadEnabled_);
     537          28 :     parseValue(node, ECHO_CANCEL_KEY, echoCanceller_);
     538          28 : }
     539             : 
     540             : #ifdef ENABLE_VIDEO
     541          37 : VideoPreferences::VideoPreferences()
     542          37 :     : decodingAccelerated_(true)
     543          37 :     , encodingAccelerated_(false)
     544          37 :     , recordPreview_(true)
     545          37 :     , recordQuality_(0)
     546          37 :     , conferenceResolution_(DEFAULT_CONFERENCE_RESOLUTION)
     547          37 : {}
     548             : 
     549             : void
     550        2399 : VideoPreferences::serialize(YAML::Emitter& out) const
     551             : {
     552        2399 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     553        2399 :     out << YAML::Key << RECORD_PREVIEW_KEY << YAML::Value << recordPreview_;
     554        2399 :     out << YAML::Key << RECORD_QUALITY_KEY << YAML::Value << recordQuality_;
     555             : #ifdef ENABLE_HWACCEL
     556        2399 :     out << YAML::Key << DECODING_ACCELERATED_KEY << YAML::Value << decodingAccelerated_;
     557        2399 :     out << YAML::Key << ENCODING_ACCELERATED_KEY << YAML::Value << encodingAccelerated_;
     558             : #endif
     559        2399 :     out << YAML::Key << CONFERENCE_RESOLUTION_KEY << YAML::Value << conferenceResolution_;
     560        2399 :     if (auto dm = getVideoDeviceMonitor())
     561        2393 :         dm->serialize(out);
     562        2399 :     out << YAML::EndMap;
     563        2399 : }
     564             : 
     565             : void
     566          28 : VideoPreferences::unserialize(const YAML::Node& in)
     567             : {
     568             :     // values may or may not be present
     569          28 :     const auto& node = in[CONFIG_LABEL];
     570             :     try {
     571          28 :         parseValue(node, RECORD_PREVIEW_KEY, recordPreview_);
     572          28 :         parseValue(node, RECORD_QUALITY_KEY, recordQuality_);
     573           0 :     } catch (...) {
     574           0 :         recordPreview_ = true;
     575           0 :         recordQuality_ = 0;
     576           0 :     }
     577             : #ifdef ENABLE_HWACCEL
     578             :     try {
     579          28 :         parseValue(node, DECODING_ACCELERATED_KEY, decodingAccelerated_);
     580          28 :         parseValue(node, ENCODING_ACCELERATED_KEY, encodingAccelerated_);
     581           0 :     } catch (...) {
     582           0 :         decodingAccelerated_ = true;
     583           0 :         encodingAccelerated_ = false;
     584           0 :     }
     585             : #endif
     586             :     try {
     587          28 :         parseValue(node, CONFERENCE_RESOLUTION_KEY, conferenceResolution_);
     588           0 :     } catch (...) {
     589           0 :         conferenceResolution_ = DEFAULT_CONFERENCE_RESOLUTION;
     590           0 :     }
     591          28 :     if (auto dm = getVideoDeviceMonitor())
     592          28 :         dm->unserialize(in);
     593          28 : }
     594             : #endif // ENABLE_VIDEO
     595             : 
     596             : #ifdef ENABLE_PLUGIN
     597          37 : PluginPreferences::PluginPreferences()
     598          37 :     : pluginsEnabled_(false)
     599          37 : {}
     600             : 
     601             : void
     602        2399 : PluginPreferences::serialize(YAML::Emitter& out) const
     603             : {
     604        2399 :     out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     605        2399 :     out << YAML::Key << JAMI_PLUGIN_KEY << YAML::Value << pluginsEnabled_;
     606        2399 :     out << YAML::Key << JAMI_PLUGINS_INSTALLED_KEY << YAML::Value << installedPlugins_;
     607        2399 :     out << YAML::Key << JAMI_PLUGINS_LOADED_KEY << YAML::Value << loadedPlugins_;
     608        2399 :     out << YAML::EndMap;
     609        2399 : }
     610             : 
     611             : void
     612          28 : PluginPreferences::unserialize(const YAML::Node& in)
     613             : {
     614             :     // values may or may not be present
     615          28 :     const auto& node = in[CONFIG_LABEL];
     616             :     try {
     617          28 :         parseValue(node, JAMI_PLUGIN_KEY, pluginsEnabled_);
     618           0 :     } catch (...) {
     619           0 :         pluginsEnabled_ = false;
     620           0 :     }
     621             : 
     622          28 :     const auto& installedPluginsNode = node[JAMI_PLUGINS_INSTALLED_KEY];
     623             :     try {
     624          28 :         installedPlugins_ = yaml_utils::parseVector(installedPluginsNode);
     625           0 :     } catch (...) {
     626           0 :     }
     627             : 
     628          28 :     const auto& loadedPluginsNode = node[JAMI_PLUGINS_LOADED_KEY];
     629             :     try {
     630          28 :         loadedPlugins_ = yaml_utils::parseVector(loadedPluginsNode);
     631           0 :     } catch (...) {
     632             :         // loadedPlugins_ = {};
     633           0 :     }
     634          28 : }
     635             : #endif // ENABLE_PLUGIN
     636             : 
     637             : } // namespace jami

Generated by: LCOV version 1.14