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