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 : #pragma once
19 :
20 : #ifdef HAVE_CONFIG_H
21 : #include "config.h"
22 : #endif
23 :
24 : #include "account_factory.h"
25 : #include "call_factory.h"
26 : #include "preferences.h"
27 : #include "media/audio/audiolayer.h"
28 : #include "gittransport.h"
29 :
30 : #include <dhtnet/certstore.h>
31 : #include <asio/post.hpp>
32 :
33 : #include <algorithm>
34 : #include <atomic>
35 : #include <functional>
36 : #include <map>
37 : #include <memory>
38 : #include <string>
39 : #include <vector>
40 :
41 : namespace asio {
42 : class io_context;
43 : }
44 :
45 : namespace dhtnet {
46 : class ChannelSocket;
47 : class IceTransportFactory;
48 : } // namespace dhtnet
49 :
50 : namespace jami {
51 : namespace video {
52 : class SinkClient;
53 : class VideoGenerator;
54 : } // namespace video
55 : class RingBufferPool;
56 : struct VideoManager;
57 : class Conference;
58 : class AudioLoop;
59 : class JamiAccount;
60 : class SIPVoIPLink;
61 : class JamiPluginManager;
62 :
63 : /** Manager (controller) of daemon */
64 : // TODO LIBJAMI_PUBLIC only if tests
65 : class LIBJAMI_TEST_EXPORT Manager
66 : {
67 : private:
68 : std::mutex randMutex_;
69 : std::mt19937_64 rand_;
70 :
71 : public:
72 : // TODO LIBJAMI_PUBLIC only if tests
73 : static LIBJAMI_TEST_EXPORT Manager& instance();
74 :
75 : void setAutoAnswer(bool enable);
76 :
77 : /**
78 : * General preferences configuration
79 : */
80 : Preferences preferences;
81 :
82 : /**
83 : * Voip related preferences
84 : */
85 : VoipPreference voipPreferences;
86 :
87 : /**
88 : * Audio preferences
89 : */
90 : AudioPreference audioPreference;
91 :
92 : #ifdef ENABLE_PLUGIN
93 : /**
94 : * Plugin preferences
95 : */
96 : PluginPreferences pluginPreferences;
97 : #endif
98 :
99 : #ifdef ENABLE_VIDEO
100 : /**
101 : * Video preferences
102 : */
103 : VideoPreferences videoPreferences;
104 : #endif
105 :
106 : // Manager should not be accessed until initialized.
107 : // FIXME this is an evil hack!
108 : static std::atomic_bool initialized;
109 :
110 : #if TARGET_OS_IOS
111 : static bool isIOSExtension;
112 : #endif
113 :
114 : static bool syncOnRegister;
115 :
116 : static bool autoLoad;
117 :
118 : /**
119 : * Initialisation of thread (sound) and map.
120 : * Init a new VoIPLink, audio codec and audio driver.
121 : */
122 : void init(const std::filesystem::path& config_file, libjami::InitFlag flags);
123 :
124 : /*
125 : * Terminate all threads and exit DBus loop
126 : */
127 : void finish() noexcept;
128 :
129 : void monitor(bool continuous);
130 :
131 : std::vector<std::map<std::string, std::string>> getConnectionList(const std::string& accountId,
132 : const std::string& conversationId);
133 : std::vector<std::map<std::string, std::string>> getChannelList(const std::string& accountId,
134 : const std::string& connectionId);
135 :
136 : /**
137 : * Accessor to audiodriver.
138 : * it's multi-thread and use mutex internally
139 : * @return AudioLayer* The audio layer object
140 : */
141 : std::shared_ptr<AudioLayer> getAudioDriver();
142 :
143 603 : inline std::unique_ptr<AudioDeviceGuard> startAudioStream(AudioDeviceType stream)
144 : {
145 603 : return std::make_unique<AudioDeviceGuard>(*this, stream);
146 : }
147 :
148 : /**
149 : * Start a capture stream on the given device (eg. a window handle).
150 : * If another stream is already using this device, increase its user count and return a guard.
151 : * Otherwise, start a new capture stream on the device and return a guard.
152 : * @param captureDevice The name of the capture device to use
153 : * @return A guard that will stop the capture stream when destroyed
154 : */
155 0 : inline std::unique_ptr<AudioDeviceGuard> startCaptureStream(const std::string& captureDevice)
156 : {
157 0 : return std::make_unique<AudioDeviceGuard>(*this, captureDevice);
158 : }
159 :
160 : /**
161 : * Place a new call
162 : * @param accountId the user's account ID
163 : * @param callee the callee's ID/URI. Depends on the account type.
164 : * Refer to placeCall/placeCallWithMedia documentations.
165 : * @param mediaList a list of media to include
166 : * @return the call ID on success, empty string otherwise
167 : */
168 : std::string outgoingCall(const std::string& accountId,
169 : const std::string& callee,
170 : const std::vector<libjami::MediaMap>& mediaList = {});
171 :
172 : /**
173 : * Functions which occur with a user's action
174 : * Answer the call
175 : * @param callId
176 : */
177 : bool acceptCall(const std::string& accountId,
178 : const std::string& callId,
179 : const std::vector<libjami::MediaMap>& mediaList = {});
180 : bool acceptCall(Call& call, const std::vector<libjami::MediaMap>& mediaList = {});
181 :
182 : /**
183 : * Handle incoming call and notify user
184 : * @param accountId an account id
185 : * @param call A call pointer
186 : */
187 : void incomingCall(const std::string& accountId, Call& call);
188 :
189 : /**
190 : * Functions which occur with a user's action
191 : * Hangup the call
192 : * @param accountId
193 : * @param callId The call identifier
194 : */
195 : bool hangupCall(const std::string& accountId, const std::string& callId);
196 :
197 : /**
198 : * Functions which occur with a user's action
199 : * Hangup the conference (hangup every participants)
200 : * @param id The call identifier
201 : */
202 : bool hangupConference(const std::string& accountId, const std::string& confId);
203 :
204 : /**
205 : * Functions which occur with a user's action
206 : * Hold call
207 : * @param accountId
208 : * @param callId The call identifier
209 : */
210 : bool holdCall(const std::string& accountId, const std::string& callId);
211 :
212 : /**
213 : * Functions which occur with a user's action
214 : * Resume call
215 : * @param accountId
216 : * @param id The call identifier
217 : */
218 : bool resumeCall(const std::string& accountId, const std::string& callId);
219 :
220 : /**
221 : * Functions which occur with a user's action
222 : * Transfer the call
223 : * @param id The call identifier
224 : * @param to The recipient of the transfer
225 : */
226 : bool transferCall(const std::string& accountId, const std::string& id, const std::string& to);
227 :
228 : /**
229 : * Notify the client the transfer is successful
230 : */
231 : void transferSucceeded();
232 :
233 : /**
234 : * Notify the client that the transfer failed
235 : */
236 : void transferFailed();
237 :
238 : /**
239 : * Functions which occur with a user's action
240 : * Refuse the call
241 : * @param id The call identifier
242 : */
243 : bool refuseCall(const std::string& accountId, const std::string& id);
244 :
245 : /**
246 : * Hold all conference participants
247 : * @param the conference id
248 : */
249 : bool holdConference(const std::string& accountId, const std::string& confId);
250 :
251 : /**
252 : * Resume all conference participants
253 : * @param the conference id
254 : */
255 : bool resumeConference(const std::string& accountId, const std::string& confId);
256 :
257 : /**
258 : * Add a subcall to a conference
259 : * @param the call id
260 : * @param the conference id
261 : */
262 : bool addSubCall(const std::string& accountId,
263 : const std::string& callId,
264 : const std::string& account2Id,
265 : const std::string& confId);
266 : bool addSubCall(Call& call, Conference& conference);
267 : void bindCallToConference(Call& call, Conference& conf);
268 :
269 : /**
270 : * Bind the main participant to a conference (mainly called on a double click action)
271 : * @param the conference id
272 : */
273 : bool addMainParticipant(const std::string& accountId, const std::string& confId);
274 :
275 : /**
276 : * Join two participants to create a conference
277 : * @param the fist call id
278 : * @param the second call id
279 : */
280 : bool joinParticipant(const std::string& accountId,
281 : const std::string& callId1,
282 : const std::string& account2Id,
283 : const std::string& callId2,
284 : bool attached = true);
285 :
286 : /**
287 : * Create a conference from a list of participant
288 : * @param A vector containing the list of participant
289 : */
290 : void createConfFromParticipantList(const std::string& accountId, const std::vector<std::string>&);
291 :
292 : /**
293 : * Detach a participant from a conference, put the call on hold, do not hangup it
294 : * @param call id
295 : * @param the current call id
296 : */
297 : bool detachParticipant(const std::string& callId);
298 :
299 : /**
300 : * Detach the local participant from curent conference.
301 : * Remote participants are placed on hold.
302 : */
303 : bool detachHost(const std::shared_ptr<Conference>& conf = {});
304 :
305 : /**
306 : * Remove the conference participant from a conference
307 : * @param call id
308 : */
309 : void removeParticipant(Call& call);
310 :
311 : /**
312 : * Join two conference together into one unique conference
313 : */
314 : bool joinConference(const std::string& accountId,
315 : const std::string& confId1,
316 : const std::string& account2Id,
317 : const std::string& confId2);
318 :
319 : void addAudio(Call& call);
320 :
321 : void removeAudio(Call& call);
322 :
323 : /**
324 : * Save config to file
325 : */
326 : void saveConfig();
327 : void saveConfig(const std::shared_ptr<Account>& acc);
328 :
329 : /**
330 : * Play a ringtone
331 : */
332 : void playTone();
333 :
334 : /**
335 : * Play a special ringtone ( BUSY ) if there's at least one message on the voice mail
336 : */
337 : void playToneWithMessage();
338 :
339 : /**
340 : * Acts on the audio streams and audio files
341 : */
342 : void stopTone();
343 :
344 : /**
345 : * Notify the user that the recipient of the call has answered and the put the
346 : * call in Current state
347 : * @param id The call identifier
348 : */
349 : void peerAnsweredCall(Call& call);
350 :
351 : /**
352 : * Rings back because the outgoing call is ringing and the put the
353 : * call in Ringing state
354 : * @param id The call identifier
355 : */
356 : void peerRingingCall(Call& call);
357 :
358 : /**
359 : * Put the call in Hungup state, remove the call from the list
360 : * @param id The call identifier
361 : */
362 : void peerHungupCall(Call& call);
363 :
364 : /**
365 : * Notify the client with an incoming message
366 : * @param accountId The account identifier
367 : * @param callId The call to send the message
368 : * @param messages A map if mime type as key and mime payload as value
369 : */
370 : void incomingMessage(const std::string& accountId,
371 : const std::string& callId,
372 : const std::string& from,
373 : const std::map<std::string, std::string>& messages);
374 :
375 : /**
376 : * Send a new text message to the call, if participate to a conference, send to all participant.
377 : * @param accountId
378 : * @param callId The call to send the message
379 : * @param message A list of pair of mime types and payloads
380 : * @param from The sender of this message (could be another participant of a conference)
381 : */
382 : void sendCallTextMessage(const std::string& accountId,
383 : const std::string& callID,
384 : const std::map<std::string, std::string>& messages,
385 : const std::string& from,
386 : bool isMixed);
387 :
388 : /**
389 : * ConfigurationManager - Send registration request
390 : * @param accountId The account to register/unregister
391 : * @param enable The flag for the type of registration
392 : * false for unregistration request
393 : * true for registration request
394 : */
395 : void sendRegister(const std::string& accountId, bool enable);
396 :
397 : uint64_t sendTextMessage(const std::string& accountID,
398 : const std::string& to,
399 : const std::map<std::string, std::string>& payloads,
400 : bool fromPlugin = false,
401 : bool onlyConnected = false);
402 :
403 : int getMessageStatus(uint64_t id) const;
404 : int getMessageStatus(const std::string& accountID, uint64_t id) const;
405 :
406 : /**
407 : * Get account list
408 : * @return std::vector<std::string> A list of accoundIDs
409 : */
410 : std::vector<std::string> getAccountList() const;
411 :
412 : /**
413 : * Set the account order in the config file
414 : */
415 : void setAccountsOrder(const std::string& order);
416 :
417 : /**
418 : * Retrieve details about a given account
419 : * @param accountID The account identifier
420 : * @return std::map< std::string, std::string > The account details
421 : */
422 : std::map<std::string, std::string> getAccountDetails(const std::string& accountID) const;
423 :
424 : /**
425 : * Retrieve volatile details such as recent registration errors
426 : * @param accountID The account identifier
427 : * @return std::map< std::string, std::string > The account volatile details
428 : */
429 : std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountID) const;
430 :
431 : /**
432 : * Get list of calls (internal subcalls are filter-out)
433 : * @return std::vector<std::string> A list of call IDs (without subcalls)
434 : */
435 : std::vector<std::string> getCallList() const;
436 :
437 : /**
438 : * Save the details of an existing account, given the account ID
439 : * This will load the configuration map with the given data.
440 : * It will also register/unregister links where the 'Enabled' switched.
441 : * @param accountID The account identifier
442 : * @param details The account parameters
443 : */
444 : void setAccountDetails(const std::string& accountID, const std::map<std::string, std::string>& details);
445 :
446 : void setAccountActive(const std::string& accountID, bool active, bool shutdownConnections);
447 : void loadAccountAndConversation(const std::string& accountId, bool loadAll, const std::string& convId);
448 :
449 : std::mt19937_64 getSeededRandomEngine();
450 :
451 : /**
452 : * Return a new random accountid that is not present in the list
453 : * @return A brand new accountid
454 : */
455 : std::string getNewAccountId();
456 :
457 : /**
458 : * Add a new account, and give it a new account ID automatically
459 : * @param details The new account parameters
460 : * @param accountId optionnal predetermined accountid to use
461 : * @return The account Id given to the new account
462 : */
463 : std::string addAccount(const std::map<std::string, std::string>& details, const std::string& accountId = {});
464 :
465 : void markAccountPending(const std::string& accountId);
466 : void markAccountReady(const std::string& accountId);
467 :
468 : /**
469 : * Delete an existing account, unregister VoIPLink associated, and
470 : * purge from configuration.
471 : * If 'flush' argument is true, filesystem entries are also removed.
472 : * @param accountID The account unique ID
473 : */
474 : void removeAccount(const std::string& accountID, bool flush = false);
475 :
476 : void removeAccounts();
477 :
478 : /**
479 : * Set input audio plugin
480 : * @param audioPlugin The audio plugin
481 : */
482 : void setAudioPlugin(const std::string& audioPlugin);
483 :
484 : /**
485 : * Set audio device
486 : * @param index The index of the soundcard
487 : * @param the type of stream, either PLAYBACK, CAPTURE, RINGTONE
488 : */
489 : void setAudioDevice(int index, AudioDeviceType streamType);
490 :
491 : /**
492 : * Get list of supported audio output device
493 : * @return std::vector<std::string> A list of the audio devices supporting playback
494 : */
495 : std::vector<std::string> getAudioOutputDeviceList();
496 :
497 : /**
498 : * Get list of supported audio input device
499 : * @return std::vector<std::string> A list of the audio devices supporting capture
500 : */
501 : std::vector<std::string> getAudioInputDeviceList();
502 :
503 : /**
504 : * Get string array representing integer indexes of output, input, and ringtone device
505 : * @return std::vector<std::string> A list of the current audio devices
506 : */
507 : std::vector<std::string> getCurrentAudioDevicesIndex();
508 :
509 : /**
510 : * Get index of an audio device
511 : * @param name The string description of an audio device
512 : * @return int His index
513 : */
514 : int getAudioInputDeviceIndex(const std::string& name);
515 : int getAudioOutputDeviceIndex(const std::string& name);
516 :
517 : /**
518 : * Get current alsa plugin
519 : * @return std::string The Alsa plugin
520 : */
521 : std::string getCurrentAudioOutputPlugin() const;
522 :
523 : /**
524 : * Get the noise reduction engine state from
525 : * the current audio layer.
526 : */
527 : std::string getNoiseSuppressState() const;
528 :
529 : /**
530 : * Set the noise reduction engine state in the current
531 : * audio layer.
532 : */
533 : void setNoiseSuppressState(const std::string& state);
534 :
535 : /**
536 : * Get the echo cancellation engine state in
537 : * the current audio layer.
538 : * @return std::string The current state of echoCancel
539 : */
540 : std::string getEchoCancellationState() const;
541 :
542 : /**
543 : * Get the echo cancellation engine state from
544 : * the current audio layer.
545 : */
546 : void setEchoCancellationState(const std::string& state);
547 :
548 : /**
549 : * Get the voice activity detection engine state from
550 : * the current audio layer.
551 : * @return bool The current state of voice activity detection
552 : */
553 : bool getVoiceActivityDetectionState() const;
554 :
555 : /**
556 : * Set the voice activity detection engine state in the current
557 : * audio layer.
558 : */
559 : void setVoiceActivityDetectionState(bool state);
560 :
561 : bool isAGCEnabled() const;
562 : void setAGCState(bool enabled);
563 :
564 : /**
565 : * Get is always recording functionality
566 : */
567 : bool getIsAlwaysRecording() const;
568 :
569 : /**
570 : * Set is always recording functionality, every calls will then be set in RECORDING mode
571 : * once answered
572 : */
573 : void setIsAlwaysRecording(bool isAlwaysRec);
574 :
575 : /**
576 : * Set recording on / off
577 : * Start recording
578 : * @param id The call identifier
579 : * Returns true if the call was set to record
580 : */
581 : bool toggleRecordingCall(const std::string& accountId, const std::string& id);
582 :
583 : /**
584 : * Start playback fo a recorded file if and only if audio layer is not already started.
585 : * @param File path of the file to play
586 : */
587 : bool startRecordedFilePlayback(const std::string&);
588 :
589 : void recordingPlaybackSeek(const double value);
590 :
591 : /**
592 : * Stop playback of recorded file
593 : */
594 : void stopRecordedFilePlayback();
595 :
596 : /**
597 : * Set the maximum number of days to keep in the history
598 : * @param calls The number of days
599 : */
600 : void setHistoryLimit(int days);
601 :
602 : /**
603 : * Get the maximum number of days to keep in the history
604 : * @return double The number of days
605 : */
606 : int getHistoryLimit() const;
607 :
608 : /**
609 : * Set ringing timeout (number of seconds after which a call will
610 : * enter BUSY state if not answered).
611 : * @param timeout in seconds
612 : */
613 : void setRingingTimeout(std::chrono::seconds timeout);
614 :
615 : /**
616 : * Get ringing timeout (number of seconds after which a call will
617 : * enter BUSY state if not answered).
618 : * @return timeout in seconds
619 : */
620 : std::chrono::seconds getRingingTimeout() const;
621 :
622 : /**
623 : * Get the audio manager
624 : * @return int The audio manager
625 : * "alsa"
626 : * "pulseaudio"
627 : */
628 : std::string getAudioManager() const;
629 :
630 : /**
631 : * Set the audio manager
632 : * @return true if api is now in use, false otherwise
633 : */
634 : bool setAudioManager(const std::string& api);
635 :
636 : /**
637 : * Callback called when the audio layer initialised with its
638 : * preferred format.
639 : */
640 : AudioFormat hardwareAudioFormatChanged(AudioFormat format);
641 :
642 : /**
643 : * Should be called by any component dealing with an external
644 : * audio source, indicating the format used so the mixer format
645 : * can be eventually adapted.
646 : * @returns the new format used by the main buffer.
647 : */
648 : AudioFormat audioFormatUsed(AudioFormat format);
649 :
650 : /**
651 : * Handle audio sounds heard by a caller while they wait for their
652 : * connection to a called party to be completed.
653 : */
654 : void ringback();
655 :
656 : /**
657 : * Handle played music when an incoming call occurs
658 : */
659 : void playRingtone(const std::string& accountID);
660 :
661 : /**
662 : * Handle played music when a congestion occurs
663 : */
664 : void congestion();
665 :
666 : /**
667 : * Play the dtmf-associated sound
668 : * @param code The pressed key
669 : */
670 : void playDtmf(char code);
671 :
672 : /**
673 : * Handle played sound when a call is unable to be completed because of a busy recipient
674 : */
675 : void callBusy(Call& call);
676 :
677 : /**
678 : * Handle played sound when a failure occurs
679 : */
680 : void callFailure(Call& call);
681 :
682 : /**
683 : * Retrieve the current telephone tone
684 : * @return AudioLoop* The audio tone or 0 if no tone (init before calling this function)
685 : */
686 : std::shared_ptr<AudioLoop> getTelephoneTone();
687 :
688 : /**
689 : * Retrieve the current telephone file
690 : * @return AudioLoop* The audio file or 0 if the wav is stopped
691 : */
692 : std::shared_ptr<AudioLoop> getTelephoneFile();
693 :
694 : /**
695 : * @return true is there is one or many incoming call waiting
696 : * new call, not answered or refused
697 : */
698 : bool incomingCallsWaiting();
699 :
700 : /**
701 : * Get the current call
702 : * @return std::shared_ptr<Call> A call shared pointer (could be empty)
703 : */
704 : std::shared_ptr<Call> getCurrentCall() const;
705 :
706 : /**
707 : * Get the current call id
708 : * @return std::string The call id or ""
709 : */
710 : const std::string& getCurrentCallId() const;
711 :
712 : /**
713 : * Check if a call is the current one
714 : * @param call the new call
715 : * @return bool True if the call is the current
716 : */
717 : bool isCurrentCall(const Call& call) const;
718 :
719 : /**
720 : * Load the accounts order set by the user from the jamirc config file
721 : * @return std::vector<std::string> A vector containing the account ID's
722 : */
723 : std::vector<std::string_view> loadAccountOrder() const;
724 :
725 : /**
726 : * Load the account map from configuration
727 : */
728 : int loadAccountMap(const YAML::Node& node);
729 :
730 : /**
731 : * Get the Call referred by callID. If the Call does not exist, return
732 : * empty std::shared_ptr<Call> instance
733 : */
734 : std::shared_ptr<Call> getCallFromCallID(const std::string& callID) const;
735 :
736 : /**
737 : * Return a pointer to the instance of the RingBufferPool
738 : */
739 : RingBufferPool& getRingBufferPool();
740 :
741 : /**
742 : * Tell if there is a current call processed
743 : * @return bool True if there is a current call
744 : */
745 : bool hasCurrentCall() const;
746 :
747 : /**
748 : * Get an account pointer, looks for account of type T
749 : * @param accountID account ID to get
750 : * @return std::shared_ptr<Account> Shared pointer on an Account instance or nullptr if not found
751 : */
752 : template<class T = Account>
753 18684 : inline std::shared_ptr<T> getAccount(std::string_view accountId) const
754 : {
755 18684 : return accountFactory.getAccount<T>(accountId);
756 : }
757 :
758 : /**
759 : * Get a list of account pointers of type T (baseclass Account)
760 : * @return a sorted vector of all accounts of type T
761 : */
762 : template<class T = Account>
763 3675 : std::vector<std::shared_ptr<T>> getAllAccounts() const
764 : {
765 3675 : const auto& account_order = loadAccountOrder();
766 3675 : const auto& all_accounts = accountFactory.getAllAccounts<T>();
767 3675 : std::vector<std::shared_ptr<T>> accountList;
768 3675 : accountList.reserve(all_accounts.size());
769 11764 : for (const auto& id : account_order) {
770 16168 : if (auto acc = accountFactory.getAccount<T>(id))
771 8079 : accountList.emplace_back(std::move(acc));
772 : }
773 11803 : for (auto& account : all_accounts) {
774 8128 : if (std::find(accountList.begin(), accountList.end(), account) == accountList.end())
775 49 : accountList.emplace_back(std::move(account));
776 : }
777 7350 : return accountList;
778 3675 : }
779 :
780 : template<class T = Account>
781 3525 : std::size_t accountCount() const
782 : {
783 3525 : return accountFactory.accountCount<T>();
784 : }
785 :
786 : template<class T>
787 : inline std::shared_ptr<T> findAccount(const std::function<bool(const std::shared_ptr<T>&)>& pred)
788 : {
789 : for (const auto& account : getAllAccounts<T>()) {
790 : if (pred(account))
791 : return account;
792 : }
793 : return {};
794 : }
795 :
796 : // only used by test framework
797 : bool hasAccount(const std::string& accountID);
798 :
799 : /**
800 : * Send registration for all enabled accounts
801 : */
802 : void registerAccounts();
803 :
804 : /**
805 : * Send registration for one account
806 : */
807 : void registerAccount(const std::string& accountID, const std::string& convId = {});
808 :
809 : /**
810 : * Send unregister for all enabled accounts
811 : */
812 : void unregisterAccounts();
813 :
814 : /**
815 : * Create a new outgoing call
816 : * @param toUrl Destination address
817 : * @param accountId local account
818 : * @param mediaList the list of medias
819 : * @return A (shared) pointer of Call class type.
820 : * @note This function raises VoipLinkException() on error.
821 : */
822 : std::shared_ptr<Call> newOutgoingCall(std::string_view toUrl,
823 : const std::string& accountId,
824 : const std::vector<libjami::MediaMap>& mediaList);
825 :
826 : CallFactory callFactory;
827 :
828 : const std::shared_ptr<dhtnet::IceTransportFactory>& getIceTransportFactory();
829 :
830 : std::shared_ptr<asio::io_context> ioContext() const;
831 : std::shared_ptr<dhtnet::upnp::UPnPContext> upnpContext() const;
832 :
833 : std::map<std::string, std::string> getNearbyPeers(const std::string& accountID);
834 :
835 : #ifdef ENABLE_VIDEO
836 : /**
837 : * Create a new SinkClient instance, store it in an internal cache as a weak_ptr
838 : * and return it as a shared_ptr. If a SinkClient is already stored for the given id,
839 : * this method returns this instance.
840 : * @param id SinkClient identifier as a string. Default is empty.
841 : * @param mixer true if the SinkCient is the sink of a VideoMixer node. Default is false.
842 : * @return share_ptr<SinkClient> A shared pointer on the created instance.
843 : */
844 : std::shared_ptr<video::SinkClient> createSinkClient(const std::string& id = "", bool mixer = false);
845 :
846 : /**
847 : * Create a SinkClient instance for each participant in a conference, store it in an internal
848 : * cache as a weak_ptr and populates sinksMap with sink ids and shared_ptrs.
849 : * @param callId
850 : * @param infos ConferenceInfos that will create the sinks
851 : * @param videoStream the the VideoFrameActiveWriter to which the sinks should be attached
852 : * @param sinksMap A map between sink ids and the respective shared pointer.
853 : */
854 : void createSinkClients(const std::string& callId,
855 : const ConfInfo& infos,
856 : const std::vector<std::shared_ptr<video::VideoFrameActiveWriter>>& videoStreams,
857 : std::map<std::string, std::shared_ptr<video::SinkClient>>& sinksMap,
858 : const std::string& accountId = "");
859 :
860 : /**
861 : * Return an existing SinkClient instance as a shared_ptr associated to the given identifier.
862 : * Return an empty shared_ptr (nullptr) if nothing found.
863 : * @param id SinkClient identifier as a string.
864 : * @return share_ptr<SinkClient> A shared pointer on the found instance. Empty if not found.
865 : */
866 : std::shared_ptr<video::SinkClient> getSinkClient(const std::string& id);
867 :
868 : #endif // ENABLE_VIDEO
869 : VideoManager* getVideoManager() const;
870 :
871 : unsigned dhtLogLevel {0}; // default = disable
872 : unsigned dhtnetLogLevel {0}; // default = disable
873 : AccountFactory accountFactory;
874 :
875 : std::vector<libjami::Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp);
876 :
877 : SIPVoIPLink& sipVoIPLink() const;
878 : #ifdef ENABLE_PLUGIN
879 : JamiPluginManager& getJamiPluginManager() const;
880 : #endif
881 : /**
882 : * Return current git socket used for a conversation
883 : * @param accountId Related account
884 : * @param deviceId Related device
885 : * @param conversationId Related conversation
886 : * @return std::optional<std::weak_ptr<ChannelSocket>> the related socket
887 : */
888 : std::shared_ptr<dhtnet::ChannelSocket> gitSocket(std::string_view accountId,
889 : std::string_view deviceId,
890 : std::string_view conversationId);
891 :
892 : void setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state);
893 : std::vector<std::string> getDefaultModerators(const std::string& accountID);
894 : void enableLocalModerators(const std::string& accountID, bool state);
895 : bool isLocalModeratorsEnabled(const std::string& accountID);
896 : void setAllModerators(const std::string& accountID, bool allModerators);
897 : bool isAllModerators(const std::string& accountID);
898 :
899 : void insertGitTransport(git_smart_subtransport* tr, std::unique_ptr<P2PSubTransport>&& sub);
900 : void eraseGitTransport(git_smart_subtransport* tr);
901 :
902 : dhtnet::tls::CertificateStore& certStore(const std::string& accountId) const;
903 :
904 : private:
905 : Manager();
906 : ~Manager();
907 : friend class AudioDeviceGuard;
908 :
909 : // Data members
910 : struct ManagerPimpl;
911 : std::unique_ptr<ManagerPimpl> pimpl_;
912 : };
913 :
914 : class AudioDeviceGuard
915 : {
916 : public:
917 : AudioDeviceGuard(Manager& manager, AudioDeviceType type);
918 : AudioDeviceGuard(Manager& manager, const std::string& captureDevice);
919 : ~AudioDeviceGuard();
920 :
921 : private:
922 : Manager& manager_;
923 : const AudioDeviceType type_;
924 : const std::string captureDevice_;
925 : };
926 :
927 : // Helper to install a callback to be called once by the main event loop
928 : template<typename Callback>
929 : static void
930 13080 : runOnMainThread(Callback&& cb)
931 : {
932 26160 : asio::post(*Manager::instance().ioContext(), [cb = std::forward<Callback>(cb)]() mutable {
933 : try {
934 13080 : cb();
935 0 : } catch (const std::exception& e) {
936 0 : JAMI_ERROR("Exception running job: {}", e.what());
937 : }
938 : });
939 13080 : }
940 :
941 : } // namespace jami
|