diff --git a/daemon/src/dbus/configurationmanager.cpp b/daemon/src/dbus/configurationmanager.cpp index 40374d99431a6898fb503644399eb75caf31db29..f1043603cb7ce6d805b6fe82e7fe9728ac3a85e3 100644 --- a/daemon/src/dbus/configurationmanager.cpp +++ b/daemon/src/dbus/configurationmanager.cpp @@ -389,13 +389,13 @@ void ConfigurationManager::setAddressbookList( std::map<std::string, std::string> ConfigurationManager::getHookSettings() { - return Manager::instance().getHookSettings(); + return Manager::instance().hookPreference.toMap(); } void ConfigurationManager::setHookSettings(const std::map<std::string, std::string>& settings) { - Manager::instance().setHookSettings(settings); + Manager::instance().hookPreference = HookPreference(settings); } void ConfigurationManager::setAccountsOrder(const std::string& order) diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 4c1e8cbc4f07e259d2073af9acfdfeb8df0e08b9..a9b190d1ad311a14c10e0b6d12b8097d43343a7c 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -191,9 +191,7 @@ bool ManagerImpl::outgoingCall(const std::string& account_id, std::string current_call_id(getCurrentCallId()); - std::string prefix; - if (hookPreference.getNumberEnabled()) - prefix = hookPreference.getNumberAddPrefix(); + std::string prefix(hookPreference.getNumberAddPrefix()); std::string to_cleaned(NumberCleaner::clean(to, prefix)); @@ -2748,30 +2746,6 @@ std::vector<std::string> ManagerImpl::getAddressbookList() const return unserialize(addressbookPreference.getList()); } -std::map<std::string, std::string> ManagerImpl::getHookSettings() const -{ - std::map<std::string, std::string> settings; - - settings["URLHOOK_IAX2_ENABLED"] = hookPreference.getIax2Enabled() ? "true" : "false"; - settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = hookPreference.getNumberAddPrefix(); - settings["PHONE_NUMBER_HOOK_ENABLED"] = hookPreference.getNumberEnabled() ? "true" : "false"; - settings["URLHOOK_SIP_ENABLED"] = hookPreference.getSipEnabled() ? "true" : "false"; - settings["URLHOOK_COMMAND"] = hookPreference.getUrlCommand(); - settings["URLHOOK_SIP_FIELD"] = hookPreference.getUrlSipField(); - - return settings; -} - -void ManagerImpl::setHookSettings(const std::map<std::string, std::string>& settings) -{ - hookPreference.setIax2Enabled(settings.find("URLHOOK_IAX2_ENABLED")->second == "true"); - hookPreference.setNumberAddPrefix(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second); - hookPreference.setNumberEnabled(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true"); - hookPreference.setSipEnabled(settings.find("URLHOOK_SIP_ENABLED")->second == "true"); - hookPreference.setUrlCommand(settings.find("URLHOOK_COMMAND")->second); - hookPreference.setUrlSipField(settings.find("URLHOOK_SIP_FIELD")->second); -} - void ManagerImpl::setIPToIPForCall(const std::string& callID, bool IPToIP) { if (not isIPToIP(callID)) // no IPToIP calls with the same ID diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 19ff01b301885535cab3d9ed3fd7ac6b9c1773c6..432f65adb2abcd74733c01632dfb8669529b5571 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -691,17 +691,6 @@ class ManagerImpl { */ std::vector <std::string> getAddressbookList() const; - /** - * Hook configuration - */ - std::map<std::string, std::string> getHookSettings() const; - - /** - * Hook configuration - */ - void setHookSettings(const std::map<std::string, std::string>& settings); - - /** * Get the audio manager * @return int The audio manager diff --git a/daemon/src/preferences.cpp b/daemon/src/preferences.cpp index 7b8f93dc97ebfa328719e28e7a72db05ead5e9db..caa7623b7ea86f25f262ec4ebdbc8e689537e511 100644 --- a/daemon/src/preferences.cpp +++ b/daemon/src/preferences.cpp @@ -33,6 +33,7 @@ #include "audio/pulseaudio/pulselayer.h" #include "config/yamlemitter.h" #include "config/yamlnode.h" +#include "hooks/urlhook.h" #include <sstream> #include "global.h" #include <cassert> @@ -216,6 +217,28 @@ HookPreference::HookPreference() : iax2Enabled_(false) , urlSipField_("X-sflphone-url") {} +HookPreference::HookPreference(const std::map<std::string, std::string> &settings) : + iax2Enabled_(settings.find("URLHOOK_IAX2_ENABLED")->second == "true") + , numberAddPrefix_(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second) + , numberEnabled_(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true") + , sipEnabled_(settings.find("URLHOOK_SIP_ENABLED")->second == "true") + , urlCommand_(settings.find("URLHOOK_COMMAND")->second) + , urlSipField_(settings.find("URLHOOK_SIP_FIELD")->second) +{} + +std::map<std::string, std::string> HookPreference::toMap() const +{ + std::map<std::string, std::string> settings; + settings["URLHOOK_IAX2_ENABLED"] = iax2Enabled_ ? "true" : "false"; + settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = numberAddPrefix_; + settings["PHONE_NUMBER_HOOK_ENABLED"] = numberEnabled_ ? "true" : "false"; + settings["URLHOOK_SIP_ENABLED"] = sipEnabled_ ? "true" : "false"; + settings["URLHOOK_COMMAND"] = urlCommand_; + settings["URLHOOK_SIP_FIELD"] = urlSipField_; + + return settings; +} + void HookPreference::serialize(Conf::YamlEmitter *emitter) { Conf::MappingNode preferencemap(NULL); @@ -252,6 +275,11 @@ void HookPreference::unserialize(const Conf::MappingNode *map) map->getValue(urlSipFieldKey, &urlSipField_); } +void HookPreference::run(const std::string &header) +{ + UrlHook::runAction(urlCommand_, header); +} + AudioPreference::AudioPreference() : audioApi_(PULSEAUDIO_API_STR) , cardin_(atoi(ALSA_DFT_CARD)) // ALSA_DFT_CARD diff --git a/daemon/src/preferences.h b/daemon/src/preferences.h index 8b176a579f56c1e28b7db4e3df5481e647fc20fa..24d15a524e17a27429f6473a1debbcb6eb8bdd2c 100644 --- a/daemon/src/preferences.h +++ b/daemon/src/preferences.h @@ -335,56 +335,23 @@ class AddressbookPreference : public Serializable { class HookPreference : public Serializable { public: HookPreference(); + HookPreference(const std::map<std::string, std::string> &settings); virtual void serialize(Conf::YamlEmitter *emitter); virtual void unserialize(const Conf::MappingNode *map); - bool getIax2Enabled() const { - return iax2Enabled_; - } - - void setIax2Enabled(bool i) { - iax2Enabled_ = i; - } - std::string getNumberAddPrefix() const { - return numberAddPrefix_; - } - - void setNumberAddPrefix(const std::string &n) { - numberAddPrefix_ = n; - } - - bool getNumberEnabled() const { - return numberEnabled_; - } - - void setNumberEnabled(bool n) { - numberEnabled_ = n; + if (numberEnabled_) + return numberAddPrefix_; + else + return ""; } - bool getSipEnabled() const { - return sipEnabled_; - } - - void setSipEnabled(bool s) { - sipEnabled_ = s; - } - - std::string getUrlCommand() const { - return urlCommand_; - } - void setUrlCommand(const std::string &u) { - urlCommand_ = u; - } - - std::string getUrlSipField() const { - return urlSipField_; - } - void setUrlSipField(const std::string &u) { - urlSipField_ = u; - } + std::map<std::string, std::string> toMap() const; + bool getSipEnabled() const { return sipEnabled_; } + std::string getUrlSipField() const { return urlSipField_; } + void run(const std::string &header); private: bool iax2Enabled_; @@ -393,7 +360,6 @@ class HookPreference : public Serializable { bool sipEnabled_; std::string urlCommand_; std::string urlSipField_; - }; class AudioPreference : public Serializable { diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 6ccc41a7c7cac542e17a506ff9c32dab2db3e007..9042ddc4ef684939d4c3f4c59fe9b3be6fc019bb 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -48,7 +48,6 @@ #include "dbus/dbusmanager.h" #include "dbus/callmanager.h" -#include "hooks/urlhook.h" #include "im/instant_messaging.h" #include "audio/audiolayer.h" @@ -309,7 +308,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) if (Manager::instance().hookPreference.getSipEnabled()) { std::string header_value(fetchHeaderValue(rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField())); - UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), header_value); + Manager::instance().hookPreference.run(header_value); } SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_); @@ -1240,6 +1239,31 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) pj_bool_t stun_sock_on_status_cb(pj_stun_sock *stun_sock UNUSED, pj_stun_sock_op op UNUSED, pj_status_t status) { + switch(op) { + case PJ_STUN_SOCK_DNS_OP: + DEBUG("UserAgent: Stun operation dns resolution"); + break; + case PJ_STUN_SOCK_BINDING_OP: + DEBUG("UserAgent: Stun operation binding"); + break; + case PJ_STUN_SOCK_KEEP_ALIVE_OP: + DEBUG("UserAgent: Stun operation keep alive"); + break; + case PJ_STUN_SOCK_MAPPED_ADDR_CHANGE: + DEBUG("UserAgent: Stun operation address mapping change"); + break; + default: + DEBUG("UserAgent: Stun unknown operation"); + break; + } + + if(status == PJ_SUCCESS) { + DEBUG("UserAgent: Stun operation success"); + } + else { + ERROR("UserAgent: Stun operation failure"); + } + return status == PJ_SUCCESS; } @@ -1249,7 +1273,7 @@ pj_bool_t stun_sock_on_rx_data_cb(pj_stun_sock *stun_sock UNUSED, void *pkt UNUS } -pj_status_t SIPVoIPLink::stunServerResolve(SIPAccount *account) +pj_status_t SIPVoIPLink::stunServerResolve(pj_str_t serverName, pj_uint16_t port) { pj_stun_config stunCfg; pj_stun_config_init(&stunCfg, &cp_->factory, 0, pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_)); @@ -1263,21 +1287,19 @@ pj_status_t SIPVoIPLink::stunServerResolve(SIPAccount *account) pj_stun_sock *stun_sock; pj_status_t status = pj_stun_sock_create(&stunCfg, "stunresolve", pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock); - pj_str_t stunServer = account->getStunServerName(); - if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); - ERROR("Error creating STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); + ERROR("UserAgent: Error creating STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg); return status; } - status = pj_stun_sock_start(stun_sock, &stunServer, account->getStunPort(), NULL); + status = pj_stun_sock_start(stun_sock, &serverName, port, NULL); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); - DEBUG("Error starting STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); + DEBUG("UserAgent: Error starting STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg); pj_stun_sock_destroy(stun_sock); } @@ -1354,13 +1376,13 @@ void SIPVoIPLink::createTlsTransport(SIPAccount *account, std::string remoteAddr void SIPVoIPLink::createSipTransport(SIPAccount *account) { - shutdownSipTransport(account); - if (account == NULL) { - ERROR("Account is NULL while creating sip transport"); + ERROR("UserAgent: Account is NULL while creating sip transport"); return; } + shutdownSipTransport(account); + if (account->isTlsEnabled()) { std::string remoteSipUri(account->getServerUri()); static const char SIPS_PREFIX[] = "<sips:"; @@ -1369,8 +1391,10 @@ void SIPVoIPLink::createSipTransport(SIPAccount *account) std::string remoteAddr(remoteSipUri.substr(sips, trns-sips)); createTlsTransport(account, remoteAddr); - } else if (account->isStunEnabled()) - createStunTransport(account); + } else if (account->isStunEnabled()) { + pjsip_transport *transport = createStunTransport(account->getStunServerName(), account->getStunPort()); + account->transport_ = transport; + } else { pjsip_transport *transport = createUdpTransport(account->getLocalInterface(), account->getLocalPort()); account->transport_ = transport; @@ -1448,39 +1472,43 @@ pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, return tp; } -void SIPVoIPLink::createStunTransport(SIPAccount *account) +pjsip_transport *SIPVoIPLink::createStunTransport(pj_str_t serverName, pj_uint16_t port) { - pj_str_t stunServer = account->getStunServerName(); - pj_uint16_t stunPort = PJ_STUN_PORT; // account->getStunPort(); - - DEBUG("UserAgent: Create stun transport server name: %s, port: %d", account->getStunServerName(), stunPort);// account->getStunPort()); - - if (stunServerResolve(account) != PJ_SUCCESS) { - ERROR("Can't resolve STUN server"); - return; + // pj_str_t stunServer = account->getStunServerName(); + // pj_uint16_t stunPort = PJ_STUN_PORT; // account->getStunPort(); + pjsip_transport *transport; + + DEBUG("UserAgent: Create stun transport server name: %s, port: %d", serverName, port);// account->getStunPort()); + if (stunServerResolve(serverName, port) != PJ_SUCCESS) { + ERROR("UserAgent: Can't resolve STUN server"); + // Signal client + return NULL; } pj_sock_t sock = PJ_INVALID_SOCKET; pj_sockaddr_in boundAddr; - if (pj_sockaddr_in_init(&boundAddr, &stunServer, 0) != PJ_SUCCESS) { - ERROR("Can't initialize IPv4 socket on %*s:%i", stunServer.slen, stunServer.ptr, stunPort); - return; + if (pj_sockaddr_in_init(&boundAddr, &serverName, 0) != PJ_SUCCESS) { + ERROR("UserAgent: Can't initialize IPv4 socket on %*s:%i", serverName.slen, serverName.ptr, port); + // Signal client + return NULL; } if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) { - ERROR("Can't create or bind socket"); - return; + ERROR("UserAgent: Can't create or bind socket"); + // Signal client + return NULL; } // Query the mapped IP address and port on the 'outside' of the NAT pj_sockaddr_in pub_addr; - if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &stunServer, stunPort, &stunServer, stunPort, &pub_addr) != PJ_SUCCESS) { - ERROR("Can't contact STUN server"); + if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &serverName, port, &serverName, port, &pub_addr) != PJ_SUCCESS) { + ERROR("UserAgent: Can't contact STUN server"); pj_sock_close(sock); - return; + // signal client + return NULL; } pjsip_host_port a_name = { @@ -1488,15 +1516,17 @@ void SIPVoIPLink::createStunTransport(SIPAccount *account) pj_ntohs(pub_addr.sin_port) }; - std::string listeningAddress = std::string(a_name.host.ptr, a_name.host.slen); + // std::string listeningAddress = std::string(a_name.host.ptr, a_name.host.slen); - account->setPublishedAddress(listeningAddress); - account->setPublishedPort(a_name.port); + // account->setPublishedAddress(listeningAddress); + // account->setPublishedPort(a_name.port); pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1, - &account->transport_); + &transport); pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + + return transport; } void SIPVoIPLink::shutdownSipTransport(SIPAccount *account) @@ -1544,7 +1574,6 @@ void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsi int i_port = 0; // Find the local address and port for this transport - DEBUG("transportType: %d\n", transportType); if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) { WARN("SIPVoIPLink: Could not retreive local address and port from transport, using %s:%s", addr.c_str(), port.c_str()); return; @@ -2124,14 +2153,14 @@ std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field) if (!hdr) return ""; - std::string value(std::string(hdr->hvalue.ptr, hdr->hvalue.slen)); + std::string value(hdr->hvalue.ptr, hdr->hvalue.slen); size_t pos = value.find("\n"); - if (pos == std::string::npos) + if (pos != std::string::npos) + return value.substr(0, pos); + else return ""; - - return value.substr(0, pos); } } // end anonymous namespace diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 4304d1d58d0421115921e9bb92fcf8ea21b6f14d..08bac71f5a34248c9e107958089e3066d55c5981 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -301,7 +301,7 @@ class SIPVoIPLink : public VoIPLink { /** * Resolve public address for this account */ - pj_status_t stunServerResolve(SIPAccount *); + pj_status_t stunServerResolve(pj_str_t serverName, pj_uint16_t port); /** * Create the default TLS listener. @@ -331,7 +331,7 @@ class SIPVoIPLink : public VoIPLink { * Create a UDP transport using stun server to resove public address * @param account The account for which a transport must be created. */ - void createStunTransport(SIPAccount *account); + pjsip_transport *createStunTransport(pj_str_t serverName, pj_uint16_t port); /** * UDP Transports are stored in this map in order to retreive them in case diff --git a/gnome/src/uimanager.c b/gnome/src/uimanager.c index 04ee1f5d369b77f8a771135306f4805cad15da72..d5bfe82269d678dc9f8d8ec56eebeb2161c80ac8 100644 --- a/gnome/src/uimanager.c +++ b/gnome/src/uimanager.c @@ -67,29 +67,33 @@ void show_edit_number(callable_obj_t *call); static GtkWidget *toolbar_; -static guint transferButtonConnId_; // The button toggled signal connection ID -static guint recordButtonConnId_; // The button toggled signal connection ID +// store the signal ID in case we need to +// intercept this signal +static guint transferButtonConnId_; +static guint recordButtonConnId_; static GtkAction * pickUpAction_; -static GtkWidget * pickUpWidget_; static GtkAction * newCallAction_; -static GtkWidget * newCallWidget_; static GtkAction * hangUpAction_; +static GtkAction * copyAction_; +static GtkAction * pasteAction_; +static GtkAction * recordAction_; +static GtkAction * muteAction_; +static GtkAction * voicemailAction_; +static GtkAction * imAction_; + +static GtkWidget * pickUpWidget_; +static GtkWidget * newCallWidget_; static GtkWidget * hangUpWidget_; static GtkWidget * holdMenu_; static GtkWidget * holdToolbar_; static GtkWidget * offHoldToolbar_; static GtkWidget * transferToolbar_; -static GtkAction * copyAction_; -static GtkAction * pasteAction_; -static GtkAction * recordAction_; -static GtkAction * muteAction_; static GtkWidget * recordWidget_; static GtkWidget * muteWidget_; -static GtkAction * voicemailAction_; static GtkWidget * voicemailToolbar_; static GtkWidget * imToolbar_; -static GtkAction * imAction_; + static GtkWidget * playRecordWidget_; static GtkWidget * stopRecordWidget_; @@ -130,69 +134,332 @@ call_mute(void) sflphone_mute_call(); } + +static void +update_toolbar_for_call(callable_obj_t *selectedCall, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("UIManager: Update actions for call %s", selectedCall->_callID); + + if(selectedCall == NULL) { + ERROR("Selected call is NULL while updating toolbar"); + return; + } + + // update icon in systray + show_status_hangup_icon(); + + gtk_action_set_sensitive(copyAction_, TRUE); + + switch (selectedCall->_state) { + case CALL_STATE_INCOMING: + { + DEBUG("UIManager: Call State Incoming"); + // Make the button toolbar clickable + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + // Replace the dial button with the hangup button + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_HOLD: + { + DEBUG("UIManager: Call State Hold"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_widget_set_sensitive(newCallWidget_, TRUE); + + // Replace the hold button with the off-hold button + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos++); + } + + break; + } + case CALL_STATE_RINGING: + { + DEBUG("UIManager: Call State Ringing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_DIALING: + { + DEBUG("UIManager: Call State Dialing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + + if (active_calltree_tab == current_calls_tab) + gtk_action_set_sensitive(hangUpAction_, TRUE); + + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + + if (active_calltree_tab == current_calls_tab) + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedCall->_recordfile)) { + if (selectedCall->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos++); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos++); + } + } + break; + } + case CALL_STATE_CURRENT: + { + DEBUG("UIManager: Call State Current"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) { + add_to_toolbar(toolbar_, imToolbar_, pos++); + + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + + case CALL_STATE_RECORD: + { + DEBUG("UIManager: Call State Record"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) + add_to_toolbar(toolbar_, imToolbar_, pos++); + + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + case CALL_STATE_BUSY: + case CALL_STATE_FAILURE: + { + pos = 1; + DEBUG("UIManager: Call State Busy/Failure"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + break; + } + case CALL_STATE_TRANSFER: + { + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + default: + ERROR("UIMAnager: Error: Unknown state in action update!"); + break; + } + } +} + +static void +update_toolbar_for_conference(conference_obj_t * selectedConf, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("UIManager: Update actions for conference"); + + // update icon in systray + show_status_hangup_icon(); + + switch (selectedConf->_state) { + + case CONFERENCE_STATE_ACTIVE_ATTACHED: + case CONFERENCE_STATE_ACTIVE_DETACHED: + DEBUG("UIManager: Conference State Active"); + + if (active_calltree_tab == current_calls_tab) { + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + } else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedConf->_recordfile)) { + pos = 2; + if (selectedConf->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos); + } + } + + break; + case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: + case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { + pos = 1; + DEBUG("UIManager: Conference State Record"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + + break; + } + case CONFERENCE_STATE_HOLD: + case CONFERENCE_STATE_HOLD_RECORD: { + DEBUG("UIManager: Conference State Hold"); + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + + break; + } + default: + WARN("UIManager: Error: Should not happen in action update!"); + break; + } + +} + void update_actions() { - int pos = 0; - gtk_action_set_sensitive(newCallAction_, TRUE); gtk_action_set_sensitive(pickUpAction_, FALSE); gtk_action_set_sensitive(hangUpAction_, FALSE); + gtk_action_set_sensitive(recordAction_, FALSE); + gtk_action_set_sensitive(muteAction_, FALSE); + gtk_action_set_sensitive(copyAction_, FALSE); gtk_action_set_sensitive(imAction_, FALSE); + gtk_widget_set_sensitive(holdMenu_, FALSE); + gtk_widget_set_sensitive(holdToolbar_, FALSE); + gtk_widget_set_sensitive(offHoldToolbar_, FALSE); + gtk_widget_set_sensitive(recordWidget_, FALSE); + gtk_widget_set_sensitive(muteWidget_, FALSE); + gtk_widget_set_sensitive(historyButton_, FALSE); + + // Increment the reference counter g_object_ref(hangUpWidget_); g_object_ref(recordWidget_); g_object_ref(muteWidget_); g_object_ref(holdToolbar_); g_object_ref(offHoldToolbar_); - - if (addrbook) - g_object_ref(contactButton_); - g_object_ref(historyButton_); g_object_ref(transferToolbar_); g_object_ref(voicemailToolbar_); g_object_ref(imToolbar_); + if (addrbook) + g_object_ref(contactButton_); + + // Make sure the toolbar is reinitialized + // Widget will be added according to the state + // of the selected call remove_from_toolbar(hangUpWidget_); remove_from_toolbar(recordWidget_); remove_from_toolbar(muteWidget_); remove_from_toolbar(transferToolbar_); remove_from_toolbar(historyButton_); - - if (addrbook) - remove_from_toolbar(contactButton_); - remove_from_toolbar(voicemailToolbar_); remove_from_toolbar(imToolbar_); - - gtk_widget_set_sensitive(holdMenu_, FALSE); - gtk_widget_set_sensitive(holdToolbar_, FALSE); - gtk_widget_set_sensitive(offHoldToolbar_, FALSE); - gtk_action_set_sensitive(recordAction_, FALSE); - gtk_action_set_sensitive(muteAction_, FALSE); - gtk_widget_set_sensitive(recordWidget_, FALSE); - gtk_widget_set_sensitive(muteWidget_, FALSE); - gtk_action_set_sensitive(copyAction_, FALSE); - - if (addrbook) - gtk_widget_set_sensitive(contactButton_, FALSE); - - gtk_widget_set_sensitive(historyButton_, FALSE); - - if (addrbook) - gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); - remove_from_toolbar(holdToolbar_); remove_from_toolbar(offHoldToolbar_); remove_from_toolbar(newCallWidget_); remove_from_toolbar(pickUpWidget_); - - add_to_toolbar(toolbar_, newCallWidget_, 0); - remove_from_toolbar(playRecordWidget_); remove_from_toolbar(stopRecordWidget_); + if (addrbook) { + remove_from_toolbar(contactButton_); + gtk_widget_set_sensitive(contactButton_, FALSE); + gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); + } + + // New call widget always present + add_to_toolbar(toolbar_, newCallWidget_, 0); + + // Add the history button and set it to sensitive if enabled if (eel_gconf_get_integer(HISTORY_ENABLED)) { add_to_toolbar(toolbar_, historyButton_, -1); gtk_widget_set_sensitive(historyButton_, TRUE); @@ -200,9 +467,7 @@ update_actions() GtkToolItem *separator = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), separator, -1); - // add mute button - add_to_toolbar(toolbar_, muteWidget_, -1); - gtk_action_set_sensitive(muteAction_, TRUE); + // If addressbook support has been enabled and all addressbooks are loaded, display the icon if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) { @@ -224,242 +489,9 @@ update_actions() instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED); if (selectedCall) { - DEBUG("UIManager: Update actions for call %s", selectedCall->_callID); - - // update icon in systray - show_status_hangup_icon(); - - gtk_action_set_sensitive(copyAction_, TRUE); - - switch (selectedCall->_state) { - case CALL_STATE_INCOMING: - { - DEBUG("UIManager: Call State Incoming"); - // Make the button toolbar clickable - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - // Replace the dial button with the hangup button - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_HOLD: - { - DEBUG("UIManager: Call State Hold"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_widget_set_sensitive(newCallWidget_, TRUE); - - // Replace the hold button with the off-hold button - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - case CALL_STATE_RINGING: - { - DEBUG("UIManager: Call State Ringing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_DIALING: - { - DEBUG("UIManager: Call State Dialing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - - if (active_calltree_tab == current_calls_tab) - gtk_action_set_sensitive(hangUpAction_, TRUE); - - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - - if (active_calltree_tab == current_calls_tab) - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedCall->_recordfile)) { - if (selectedCall->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos++); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos++); - } - } - break; - } - case CALL_STATE_CURRENT: - { - DEBUG("UIManager: Call State Current"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - - case CALL_STATE_RECORD: - { - DEBUG("UIManager: Call State Record"); - pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - case CALL_STATE_BUSY: - case CALL_STATE_FAILURE: - { - pos = 1; - DEBUG("UIManager: Call State Busy/Failure"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_TRANSFER: - { - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - break; - } - default: - ERROR("UIMAnager: Error: Unknown state in action update!"); - break; - } - + update_toolbar_for_call(selectedCall, instant_messaging_enabled); } else if (selectedConf) { - - DEBUG("UIManager: Update actions for conference"); - - // update icon in systray - show_status_hangup_icon(); - - switch (selectedConf->_state) { - - case CONFERENCE_STATE_ACTIVE_ATTACHED: - case CONFERENCE_STATE_ACTIVE_DETACHED: - DEBUG("UIManager: Conference State Active"); - - if (active_calltree_tab == current_calls_tab) { - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - } else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedConf->_recordfile)) { - pos = 2; - if (selectedConf->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos); - } - } - - break; - case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: - case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { - pos = 1; - DEBUG("UIManager: Conference State Record"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - case CONFERENCE_STATE_HOLD: - case CONFERENCE_STATE_HOLD_RECORD: { - DEBUG("UIManager: Conference State Hold"); - pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - default: - WARN("UIManager: Error: Should not happen in action update!"); - break; - } + update_toolbar_for_conference(selectedConf, instant_messaging_enabled); } else { // update icon in systray hide_status_hangup_icon();