/* * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. * Author: Yan Morin * Author: Laurielle Lea * Author: Emmanuel Milou * Author: Guillaume Carmel-Archambault * Author: Alexandre Savard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Additional permission under GNU GPL version 3 section 7: * * If you modify this program, or any covered work, by linking or * combining it with the OpenSSL project's OpenSSL library (or a * modified version of that library), containing parts covered by the * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. * grants you additional permission to convey the resulting work. * Corresponding Source for a non-source form of such a combination * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ #ifndef __SFL_MANAGER_H__ #define __SFL_MANAGER_H__ #include #include #include #include #include #include "dbus/dbusmanager.h" #include "config/config.h" #include "call.h" #include "conference.h" #include "audio/sound/tone.h" // for Tone::TONEID declaration #include "audio/codecs/audiocodecfactory.h" #include "audio/mainbuffer.h" #include "preferences.h" namespace sfl { class InstantMessaging; } namespace Conf { class YamlParser; class YamlEmitter; } class DTMF; class AudioFile; class AudioLayer; class TelephoneTone; class VoIPLink; #ifdef USE_ZEROCONF class DNSService; #endif class HistoryManager; class Account; /** Define a type for a AccountMap container */ typedef std::map AccountMap; /** Define a type for a std::string to std::string Map inside ManagerImpl */ typedef std::map CallAccountMap; typedef std::map CallConfigMap; /** To send multiple string */ typedef std::list TokenList; /** To store conference objects by call ids used to retreive the conference according to a call */ typedef std::map ConferenceCallMap; /** To store conference objects by conference ids */ typedef std::map ConferenceMap; static std::string default_conf = "conf"; /** Manager (controller) of sflphone daemon */ class ManagerImpl { public: ManagerImpl (void); ~ManagerImpl (void); /** * General preferences configuration */ Preferences preferences; /** * Voip related preferences */ VoipPreference voipPreferences; /** * Addressbook related preferences */ AddressbookPreference addressbookPreference; /** * Hook preferences */ HookPreference hookPreference; /** * Audio preferences */ AudioPreference audioPreference; /** * Shortcut preferences */ ShortcutPreferences shortcutPreferences; /** * Initialisation of thread (sound) and map. * Init a new VoIPLink, audio codec and audio driver */ void init (std::string config_file=""); /** * Terminate all thread (sound, link) and unload AccountMap */ void terminate (void); /** * Accessor to audiodriver. * it's multi-thread and use mutex internally * @return AudioLayer* The audio layer object */ AudioLayer* getAudioDriver (void) const { return _audiodriver; } /** * Functions which occur with a user's action * Place a new call * @param accountId The account to make tha call with * @param call_id The call identifier * @param to The recipient of the call * @param conf_id The conference identifier if any * @return bool true on success * false otherwise */ bool outgoingCall (const std::string&, const std::string&, const std::string&, const std::string& = ""); /** * Functions which occur with a user's action * Answer the call * @param id The call identifier */ bool answerCall (const std::string& id); /** * Functions which occur with a user's action * Hangup the call * @param id The call identifier */ void hangupCall (const std::string& id); /** * Functions which occur with a user's action * Hangup the conference (hangup every participants) * @param id The call identifier */ bool hangupConference (const std::string& id); /** * Functions which occur with a user's action * Put the call on hold * @param id The call identifier */ void onHoldCall (const std::string& id); /** * Functions which occur with a user's action * Put the call off hold * @param id The call identifier */ void offHoldCall (const std::string& id); /** * Functions which occur with a user's action * Transfer the call * @param id The call identifier * @param to The recipient of the transfer */ bool transferCall (const std::string& id, const std::string& to); /** * Attended transfer * @param The call id to be transfered * @param The target */ bool attendedTransfer(const std::string& transferID, const std::string& targetID); /** * Notify the client the transfer is successful */ void transferSucceded(); /** * Notify the client that the transfer failed */ void transferFailed(); /** * Functions which occur with a user's action * Refuse the call * @param id The call identifier */ bool refuseCall (const std::string& id); /** * Create a new conference given two participant * @param the first participant ID * @param the second participant ID */ Conference* createConference (const std::string& id1, const std::string& id2); /** * Delete this conference * @param the conference ID */ void removeConference (const std::string& conference_id); /** * Return the conference id for which this call is attached * @ param the call id */ Conference* getConferenceFromCallID (const std::string& call_id); /** * Hold every participant to a conference * @param the conference id */ void holdConference (const std::string& conference_id); /** * Unhold all conference participants * @param the conference id */ void unHoldConference (const std::string& conference_id); /** * Test if this id is a conference (usefull to test current call) * @param the call id */ bool isConference (const std::string& call_id); /** * Test if a call id particips to this conference * @param the call id */ bool participToConference (const std::string& call_id); /** * Add a participant to a conference * @param the call id * @param the conference id */ void addParticipant (const std::string& call_id, const std::string& conference_id); /** * Bind the main participant to a conference (mainly called on a double click action) * @param the conference id */ void addMainParticipant (const std::string& conference_id); /** * Join two participants to create a conference * @param the fist call id * @param the second call id */ void joinParticipant (const std::string& call_id1, const std::string& call_id2); /** * Create a conference from a list of participant * @param A vector containing the list of participant */ void createConfFromParticipantList(const std::vector< std::string > &); /** * Detach a participant from a conference, put the call on hold, do not hangup it * @param call id * @param the current call id */ void detachParticipant (const std::string& call_id, const std::string& current_call_id); /** * Remove the conference participant from a conference * @param call id */ void removeParticipant (const std::string& call_id); /** * Join two conference together into one unique conference */ void joinConference (const std::string& conf_id1, const std::string& conf_id2); void addStream (const std::string& call_id); void removeStream (const std::string& call_id); /** * Save config to file */ void saveConfig (void); /** * @return true if we tried to register once */ bool _hasTriedToRegister; /** * Handle choice of the DTMF-send-way * @param id: callid of the line. * @param code: pressed key. */ void sendDtmf (const std::string& id, char code); /** * Play a ringtone * @return bool True on success * false otherwise */ bool playTone (); /** * Play a special ringtone ( BUSY ) if there's at least one message on the voice mail * @return bool True on success * false otherwise */ bool playToneWithMessage (); /** * Acts on the audio streams and audio files */ void stopTone (void); /** * When receiving a new incoming call, add it to the callaccount map * and notify user * @param call A call pointer * @param accountId an account id * @return bool True if the call was added correctly */ bool incomingCall (Call* call, const std::string& accountId); /** * Notify the user that the recipient of the call has answered and the put the * call in Current state * @param id The call identifier */ void peerAnsweredCall (const std::string& id); /** * Rings back because the outgoing call is ringing and the put the * call in Ringing state * @param id The call identifier */ void peerRingingCall (const std::string& id); /** * Put the call in Hungup state, remove the call from the list * @param id The call identifier */ void peerHungupCall (const std::string& id); /** * Notify the client with an incoming message * @param accountId The account identifier * @param message The content of the message */ void incomingMessage (const std::string& callID, const std::string& from, const std::string& message); /** * Send a new text message to the call, if participate to a conference, send to all participant. * @param callID The call to send the message * @param message The content of the message * @param from The sender of this message (could be another participant of a conference) */ bool sendTextMessage (const std::string& callID, const std::string& message, const std::string& from); /** * Notify the client he has voice mails * @param accountId The account identifier * @param nb_msg The number of messages */ void startVoiceMessageNotification (const std::string& accountId, int nb_msg); /** * Notify the client through DBus that registration state has been updated */ void connectionStatusNotification (void); /** * ConfigurationManager - Send registration request * @param accountId The account to register/unregister * @param enable The flag for the type of registration * 0 for unregistration request * 1 for registration request */ void sendRegister (const ::std::string& accountId , const int32_t& enable); /** * Get account list * @return std::vector A list of accoundIDs */ std::vector< std::string > getAccountList() const; /** * Set the account order in the config file */ void setAccountsOrder (const std::string& order); /** * Retrieve details about a given account * @param accountID The account identifier * @return std::map< std::string, std::string > The account details */ std::map< std::string, std::string > getAccountDetails (const std::string& accountID) const; /** * Retrieve details about a given call * @param callID The account identifier * @return std::map< std::string, std::string > The call details */ std::map< std::string, std::string > getCallDetails (const std::string& callID); /** * Get call list * @return std::vector A list of call IDs */ std::vector< std::string > getCallList (void) const; /** * Retrieve details about a given call * @param callID The account identifier * @return std::map< std::string, std::string > The call details */ std::map< std::string, std::string > getConferenceDetails (const std::string& callID) const; /** * Get call list * @return std::vector A list of call IDs */ std::vector< std::string > getConferenceList (void) const; /** * Get a list of participant to a conference * @return std::vector A list of call IDs */ std::vector< std::string > getParticipantList (const std::string& confID) const; /** * Save the details of an existing account, given the account ID * This will load the configuration map with the given data. * It will also register/unregister links where the 'Enabled' switched. * @param accountID The account identifier * @param details The account parameters */ void setAccountDetails (const ::std::string& accountID, const std::map< ::std::string, ::std::string >& details); /** * Add a new account, and give it a new account ID automatically * @param details The new account parameters * @return The account Id given to the new account */ std::string addAccount (const std::map< ::std::string, ::std::string >& details); /** * Delete an existing account, unregister VoIPLink associated, and * purge from configuration. * @param accountID The account unique ID */ void removeAccount (const std::string& accountID); /** * Get current codec name * @param call id * @return std::string The codec name */ std::string getCurrentCodecName (const std::string& id); /** * Set input audio plugin * @param audioPlugin The audio plugin */ void setAudioPlugin (const std::string& audioPlugin); /** * Set audio device * @param index The index of the soundcard * @param the type of stream, either SFL_PCM_PLAYBACK, SFL_PCM_CAPTURE, SFL_PCM_RINGTONE */ void setAudioDevice (const int index, const int streamType); /** * Get list of supported audio output device * @return std::vector A list of the audio devices supporting playback */ std::vector getAudioOutputDeviceList (void); /** * Get list of supported audio input device * @return std::vector A list of the audio devices supporting capture */ std::vector getAudioInputDeviceList (void); /** * Get string array representing integer indexes of output, input, and ringtone device * @return std::vector A list of the current audio devices */ std::vector getCurrentAudioDevicesIndex(); /** * Get index of an audio device * @param name The string description of an audio device * @return int His index */ int getAudioDeviceIndex (const std::string &name); /** * Get current alsa plugin * @return std::string The Alsa plugin */ std::string getCurrentAudioOutputPlugin (void) const; /** * Get the noise reduction engin state from * the current audio layer. */ std::string getNoiseSuppressState (void) const; /** * Set the noise reduction engin state in the current * audio layer. */ void setNoiseSuppressState (const std::string &state); /** * Get the echo canceller engin state from * the current audio layer */ std::string getEchoCancelState(void) const; /** * Set the echo canceller engin state */ void setEchoCancelState(const std::string &state); int getEchoCancelTailLength(void) const; void setEchoCancelTailLength(int); int getEchoCancelDelay(void) const; void setEchoCancelDelay(int); /** * Convert a list of payload in a special format, readable by the server. * Required format: payloads separated with one slash. * @return std::string The serializabled string */ static std::string serialize (const std::vector &v); static std::vector unserialize (std::string v); /** * Ringtone option. * If ringtone is enabled, ringtone on incoming call use custom choice. If not, only standart tone. * @return int 1 if enabled * 0 otherwise */ int isRingtoneEnabled (const std::string& id); /** * Set the ringtone option * Inverse current value */ void ringtoneEnabled (const std::string& id); /** * Get the recording path from configuration tree * @return the string correspoding to the path */ std::string getRecordPath (void) const; /** * Set the recoding path in the configuration tree * @param a string reresenting the path */ void setRecordPath (const std::string& recPath); /** * Get is always recording functionality */ bool getIsAlwaysRecording(void) const; /** * Set is always recording functionality, every calls will then be set in RECORDING mode * once answered */ void setIsAlwaysRecording(bool isAlwaysRec); /** * Set recording on / off * Start recording * @param id The call identifier */ void setRecordingCall (const std::string& id); /** * Return true if the call is currently recorded */ bool isRecording (const std::string& id); /** * Start playback fo a recorded file if and only if audio layer is not already started. * @param File path of the file to play */ bool startRecordedFilePlayback(const std::string&); /** * Stop playback of recorded file * @param File of the file to stop */ void stopRecordedFilePlayback(const std::string&); /** * Set the maximum number of days to keep in the history * @param calls The number of days */ void setHistoryLimit (int days); /** * Get the maximum number of days to keep in the history * @return double The number of days */ int getHistoryLimit (void) const; /** * Configure the start-up option * @return int 1 if SFLphone should start in the system tray * 0 otherwise */ int isStartHidden (void); /** * Configure the start-up option * At startup, SFLphone can be displayed or start hidden in the system tray */ void startHidden (void); /** * Set the desktop mail notification level */ void setMailNotify (void); /** * Addressbook configuration */ std::map getAddressbookSettings (void) const; /** * Addressbook configuration */ void setAddressbookSettings (const std::map& settings); /** * Addressbook list */ void setAddressbookList (const std::vector< std::string >& list); /** * Addressbook list */ std::vector getAddressbookList (void) const; /** * Hook configuration */ std::map getHookSettings (void) const; /** * Hook configuration */ void setHookSettings (const std::map& settings); /** * Get the audio manager * @return int The audio manager * "alsa" * "pulseaudio" */ std::string getAudioManager (void) const; /** * Set the audio manager */ void setAudioManager (const std::string &api); void switchAudioManager (void); /** * Set the internal audio sampling rate change. Should close the audio layer and * reopen stream at different rate, */ void audioSamplingRateChanged (int); /** * Get the desktop mail notification level * @return int The mail notification level */ int32_t getMailNotify (void) const; /** * Get the list of the active codecs * @return std::vector< ::std::string > The list of active codecs */ std::vector< ::std::string > getActiveCodecList (void) const; /** * Retrieve in the configuration tree the value of a parameter in a specific section * @param section The section to look in * @param name The name of the parameter you want to get * @param arg Undocumented * @return bool true on success * false otherwise */ bool getConfig (const std::string& section, const std::string& name, TokenList& arg) const; /** * Change a specific value in the configuration tree. * This value will then be saved in the user config file sflphonedrc * @param section The section name * @param name The parameter name * @param value The new string value * @return bool true on success * false otherwise */ bool setConfig (const std::string& section, const std::string& name, const std::string& value); /** * Change a specific value in the configuration tree. * This value will then be saved in the user config file sflphonedrc * @param section The section name * @param name The parameter name * @param value The new int value * @return bool true on success * false otherwise */ bool setConfig (const std::string& section, const std::string& name, int value); /** * Get a int from the configuration tree * Throw an Conf::ConfigTreeItemException if not found * @param section The section name to look in * @param name The parameter name * @return int The int value */ int getConfigInt (const std::string& section, const std::string& name) const; /** * Get a bool from the configuration tree * Throw an Conf::ConfigTreeItemException if not found * @param section The section name to look in * @param name The parameter name * @return bool The bool value */ bool getConfigBool (const std::string& section, const std::string& name) const; /** * Get a string from the configuration tree * Throw an Conf::ConfigTreeItemException if not found * @param section The section name to look in * @param name The parameter name * @return sdt::string The string value */ std::string getConfigString (const std::string& section, const std::string& name) const; /** * Retrieve the soundcards index in the user config file and try to open audio devices * with a specific alsa plugin. * Set the audio layer sample rate */ void selectAudioDriver (void); /** * Handle audio sounds heard by a caller while they wait for their * connection to a called party to be completed. */ void ringback (); /** * Handle played music when an incoming call occurs */ void ringtone (const std::string& accountID); /** * Handle played music when a congestion occurs */ void congestion (); /** * Handle played sound when a call can not be conpleted because of a busy recipient */ void callBusy (const std::string& id); /** * Handle played sound when a failure occurs */ void callFailure (const std::string& id); /** * Retrieve the current telephone tone * @return AudioLoop* The audio tone or 0 if no tone (init before calling this function) */ AudioLoop* getTelephoneTone(); /** * Retrieve the current telephone file * @return AudioLoop* The audio file or 0 if the wav is stopped */ AudioLoop* getTelephoneFile(); /** * @return true is there is one or many incoming call waiting * new call, not anwsered or refused */ bool incomingCallWaiting (void); /* * Inline functions to manage speaker volume control * Read by main thread and AudioLayer thread * Write by main thread only * @return unsigned short The volume value */ unsigned short getSpkrVolume (void) const { return _spkr_volume; } /* * Inline functions to manage speaker volume control * Read by main thread and AudioLayer thread * Write by main thread only * @param spkr_vol The volume value */ void setSpkrVolume (unsigned short spkr_vol); /* * Inline functions to manage mic volume control * Read by main thread and AudioLayer thread * Write by main thread only * @return unsigned short The volume value */ unsigned short getMicVolume (void) const { return _mic_volume; } /* * Inline functions to manage mic volume control * Read by main thread and AudioLayer thread * Write by main thread only * @param mic_vol The volume value */ void setMicVolume (unsigned short mic_vol); /** * Return a new random callid that is not present in the list * @return std::string A brand new callid */ std::string getNewCallID(); /** * Get the current call id * @return std::string The call id or "" */ const std::string& getCurrentCallId() const; /** * Check if a call is the current one * @param callId the new callid * @return bool True if the id is the current call */ bool isCurrentCall (const std::string& callId); void initAudioDriver (void); void audioLayerMutexLock(void) { _audiolayerMutex.enterMutex(); } void audioLayerMutexUnlock(void) { _audiolayerMutex.leaveMutex(); } /** * Load the accounts order set by the user from the sflphonedrc config file * @return std::vector A vector containing the account ID's */ std::vector loadAccountOrder () const; // map of codec (for configlist request) const AudioCodecFactory audioCodecFactory; private: /** * Play the dtmf-associated sound * @param code The pressed key */ bool playDtmf (char code); /** * Process remaining participant given a conference and the current call id. * Mainly called when a participant is detached or hagned up * @param current call id * @param conference pointer */ void processRemainingParticipant (const std::string ¤t_call_id, Conference *conf); /** * Create config directory in home user and return configuration file path */ std::string getConfigFile (void) const; /* * Initialize zeroconf module and scanning */ void initZeroconf (void); /* * Init the volume for speakers/micro from 0 to 100 value */ void initVolume(); /** * Switch of current call id * @param id The new callid */ void switchCall (const std::string& id); /* * Play one tone * @return false if the driver is uninitialize */ bool playATone (Tone::TONEID toneId); DBusManager _dbus; /** The configuration tree. It contains accounts parameters, general user settings ,audio settings, ... */ Conf::ConfigTree _config; /** Current Call ID */ std::string _currentCallId2; /** Protected current call access */ ost::Mutex _currentCallMutex; /** Audio layer */ AudioLayer* _audiodriver; // Main thread DTMF* _dtmfKey; ///////////////////// // Protected by Mutex ///////////////////// ost::Mutex _toneMutex; TelephoneTone* _telephoneTone; AudioFile *_audiofile; // To handle volume control short _spkr_volume; short _mic_volume; // End of sound variable /** * Mutex used to protect audio layer */ ost::Mutex _audiolayerMutex; /** * Waiting Call Vectors */ CallIDSet _waitingCall; /** * Protect waiting call list, access by many voip/audio threads */ ost::Mutex _waitingCallMutex; /** * Number of waiting call, synchronize with waitingcall callidvector */ unsigned int _nbIncomingWaitingCall; /** * Add incoming callid to the waiting list * @param id std::string to add */ void addWaitingCall (const std::string& id); /** * Remove incoming callid to the waiting list * @param id std::string to remove */ void removeWaitingCall (const std::string& id); /** * Tell if a call is waiting and should be remove * @param id std::string to test * @return bool True if the call is waiting */ bool isWaitingCall (const std::string& id); /** * Path of the ConfigFile */ std::string _path; #ifdef USE_ZEROCONF // DNSService contain every zeroconf services // configuration detected on the network DNSService *_DNSService; #endif /** Map to associate a CallID to the good account */ CallAccountMap _callAccountMap; /** Mutex to lock the call account map (main thread + voiplink thread) */ ost::Mutex _callAccountMapMutex; CallConfigMap _callConfigMap; bool associateConfigToCall (const std::string& callID, Call::CallConfiguration config); Call::CallConfiguration getConfigFromCall (const std::string& callID) const; bool removeCallConfig (const std::string& callID); /** *Contains a list of account (sip, aix, etc) and their respective voiplink/calls */ AccountMap _accountMap; /** * Load the account from configuration */ void loadAccountMap(Conf::YamlParser *parser); /** * Unload the account (delete them) */ void unloadAccountMap(); /** * Instance of the MainBuffer for the whole application * * In order to send signal to other parts of the application, one must pass through the mainbuffer. * Audio instances must be registered into the MainBuffer and bound together via the ManagerImpl. * */ MainBuffer _mainBuffer; public: /** Associate a new std::string to a std::string * Protected by mutex * @param callID the new CallID not in the list yet * @param accountID the known accountID present in accountMap * @return bool True if the new association is create */ bool associateCallToAccount (const std::string& callID, const std::string& accountID); /** Remove a CallID/std::string association * Protected by mutex * @param callID the CallID to remove * @return bool True if association is removed */ bool removeCallAccount (const std::string& callID); /** * Test if call is a valid call, i.e. have been created and stored in * call-account map * @param callID the std::string to be tested * @return true if call is created and present in the call-account map */ bool isValidCall(const std::string& callID); /** * Return a pointer to the instance of the mainbuffer */ MainBuffer *getMainBuffer (void) { return &_mainBuffer; } /** * Return a pointer to the instance of InstantMessaging */ sfl::InstantMessaging *getInstantMessageModule (void) const { return _imModule; } /** * Tell if there is a current call processed * @return bool True if there is a current call */ bool hasCurrentCall(); /** * Return the current DBusManager * @return A pointer to the DBusManager instance */ DBusManager * getDbusManager() { return &_dbus; } /** * Tell if an account exists * @param accountID account ID check * @return bool True if the account exists * false otherwise */ bool accountExists (const std::string& accountID); /** * Get a list of serialized history entries * @return A list of serialized entry */ std::vector getHistorySerialized (void) const; /** * Set a list of serialized history entries * @param Vector of history entries */ void setHistorySerialized (std::vector history); /** * Get an account pointer * @param accountID account ID to get * @return Account* The account pointer or 0 */ Account* getAccount (const std::string& accountID) const; /** Return the std::string from a CallID * Protected by mutex * @param callID the CallID in the list * @return std::string The accountID associated or "" if the callID is not found */ std::string getAccountFromCall (const std::string& callID); /** * Get the voip link from the account pointer * @param accountID Account ID to get * @return VoIPLink* The voip link from the account pointer or 0 */ VoIPLink* getAccountLink (const std::string& accountID="") const; std::string getAccountIdFromNameAndServer (const std::string& userName, const std::string& server) const; int getLocalIp2IpPort() const; std::string getStunServer (void) const; void setStunServer (const std::string &server); int isStunEnabled (void); void enableStun (void); // Map containing reference between conferences and calls ConferenceCallMap _conferencecall; // Map containing conference pointers ConferenceMap _conferencemap; /** * Send registration to all enabled accounts */ void registerAccounts(); private: // Copy Constructor ManagerImpl (const ManagerImpl& rh); // Assignment Operator ManagerImpl& operator= (const ManagerImpl& rh); /** * To handle the persistent history */ HistoryManager * _history; /** * Instant messaging module, resposible to initiate, format, parse, * send, and receive instant messages. */ sfl::InstantMessaging *_imModule; /** * Check if the call is a classic call or a direct IP-to-IP call */ void checkCallConfiguration (const std::string& id, const std::string& to, Call::CallConfiguration *callConfig); Conf::YamlEmitter *emitter; }; #endif // __MANAGER_H__