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