LCOV - code coverage report
Current view: top level - src - preferences.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 88.5 % 278 246
Test Date: 2026-07-06 08:25:38 Functions: 75.0 % 40 30

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

Generated by: LCOV version 2.0-1