LCOV - code coverage report
Current view: top level - src - preferences.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 86.3 % 278 240
Test Date: 2026-06-13 09:18:46 Functions: 72.5 % 40 29

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

Generated by: LCOV version 2.0-1