diff --git a/src/gui/official/Call.hpp b/src/gui/official/Call.hpp index 492c9e88a..d1272b207 100644 --- a/src/gui/official/Call.hpp +++ b/src/gui/official/Call.hpp @@ -41,7 +41,7 @@ class Call */ bool isIncomming(); - std::string id() + std::string id() const {return mId;} std::string call(const std::string &to); diff --git a/src/gui/official/CallStatus.cpp b/src/gui/official/CallStatus.cpp new file mode 100644 index 000000000..34630e3df --- /dev/null +++ b/src/gui/official/CallStatus.cpp @@ -0,0 +1,36 @@ +#include "globals.h" + +#include "CallStatus.hpp" +#include "PhoneLineManager.hpp" + +CallStatus::CallStatus(const std::string &code, + const std::list< std::string > &args) + : CallRelatedEvent(code, args) +{ + std::list< std::string > l = getUnusedArgs(); + if(l.size() >= 3) { + mAccountId = *l.begin(); + l.pop_front(); + mDestination = *l.begin(); + l.pop_front(); + mStatus = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +CallStatus::execute() +{ + std::string id = getCallId(); + if(id.size() > 0) { + _debug("%s status received for call ID: %s.\n", + mStatus.c_str(), + id.c_str()); + PhoneLineManager::instance().addCall(mAccountId, getCallId(), mDestination, mStatus); + } + else { + _debug("Status invalid: %s\n", toString().c_str()); + } +} + diff --git a/src/gui/official/CallStatus.hpp b/src/gui/official/CallStatus.hpp new file mode 100644 index 000000000..1caabac5a --- /dev/null +++ b/src/gui/official/CallStatus.hpp @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * + * + * 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 2 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. + */ + +#ifndef __CALLSTATUS_HPP__ +#define __CALLSTATUS_HPP__ + +#include "Event.hpp" + +class CallStatus : public CallRelatedEvent +{ +public: + CallStatus(const std::string &code, + const std::list< std::string > &args); + + void execute(); + +protected: + std::string mAccountId; + std::string mDestination; + std::string mStatus; +}; + +#endif + diff --git a/src/gui/official/CallStatusFactory.hpp b/src/gui/official/CallStatusFactory.hpp new file mode 100644 index 000000000..83e467b6e --- /dev/null +++ b/src/gui/official/CallStatusFactory.hpp @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * + * + * 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 2 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. + */ + +#ifndef __CALLSTATUSFACTORY_HPP__ +#define __CALLSTATUSFACTORY_HPP__ + +#include "EventFactory.hpp" + +typedef utilspp::SingletonHolder< EventFactoryImpl< Event > > CallStatusFactory; + +#endif + diff --git a/src/gui/official/Event.cpp b/src/gui/official/Event.cpp index cabb01962..3fe9cab32 100644 --- a/src/gui/official/Event.cpp +++ b/src/gui/official/Event.cpp @@ -2,7 +2,6 @@ #include "Call.hpp" #include "Event.hpp" -#include "PhoneLineManager.hpp" Event::Event(const std::string &code, const std::list< std::string > &args) @@ -15,7 +14,7 @@ Event::Event(const std::string &code, void Event::execute() { - _debug("Received: %s.\n", toString().c_str()); + _debug("Received: %s\n", toString().c_str()); } std::string @@ -48,48 +47,3 @@ CallRelatedEvent::getCallId() { return mCallId; } - -HangupEvent::HangupEvent(const std::string &code, - const std::list< std::string > &args) - : CallRelatedEvent(code, args) -{} - -void -HangupEvent::execute() -{ - std::string id = getCallId(); - if(id.size() > 0) { - _debug("Hangup Event received for call ID: %s.\n", id.c_str()); - PhoneLineManager::instance().hangup(id); - } - else { - _debug("Hangup Event invalid (missing call ID): %s\n", toString().c_str()); - } -} - -IncommingEvent::IncommingEvent(const std::string &code, - const std::list< std::string > &args) - : CallRelatedEvent(code, args) -{ - std::list< std::string > l; - if(getUnusedArgs().size() >= 3) { - mAccountId = *l.begin(); - l.pop_front(); - mOrigin = *l.begin(); - l.pop_front(); - setUnusedArgs(l); - } -} - -void -IncommingEvent::execute() -{ - std::string id = getCallId(); - if(id.size() > 0) { - _debug("Hangup Event received for call ID: %s.\n", id.c_str()); - PhoneLineManager::instance().incomming(mAccountId, mOrigin, getCallId()); - } - else { - _debug("Event invalid: %s\n", toString().c_str()); - } -} diff --git a/src/gui/official/Event.hpp b/src/gui/official/Event.hpp index 015050449..64e0998d2 100644 --- a/src/gui/official/Event.hpp +++ b/src/gui/official/Event.hpp @@ -59,27 +59,5 @@ private: std::string mCallId; }; -class HangupEvent : public CallRelatedEvent -{ -public: - HangupEvent(const std::string &code, - const std::list< std::string > &args); - - virtual void execute(); -}; - -class IncommingEvent : public CallRelatedEvent -{ -public: - IncommingEvent(const std::string &code, - const std::list< std::string > &args); - - virtual void execute(); - -private: - std::string mAccountId; - std::string mOrigin; -}; - #endif diff --git a/src/gui/official/PhoneLine.cpp b/src/gui/official/PhoneLine.cpp index 56d2a7c03..4ab85c546 100644 --- a/src/gui/official/PhoneLine.cpp +++ b/src/gui/official/PhoneLine.cpp @@ -37,18 +37,20 @@ PhoneLine::unlock() } void -PhoneLine::select() +PhoneLine::select(bool hardselect) { if(!mSelected) { _debug("PhoneLine %d: I am selected.\n", mLine); mSelected = true; - if(mCall) { - if(mCall->isIncomming()) { - mCall->answer(); - } - else { - mCall->unhold(); + if(!hardselect) { + if(mCall) { + if(mCall->isIncomming()) { + mCall->answer(); + } + else { + mCall->unhold(); + } } } @@ -56,14 +58,29 @@ PhoneLine::select() } } +void +PhoneLine::disconnect() +{ + mSelected = false; + _debug("PhoneLine %d: I am disconnected.\n", mLine); + if(mCall) { + delete mCall; + mCall = NULL; + } + + emit unselected(); +} + void -PhoneLine::unselect() +PhoneLine::unselect(bool hardselect) { if(mSelected) { _debug("PhoneLine %d: I am unselected.\n", mLine); mSelected = false; if(mCall) { - mCall->hold(); + if(!hardselect) { + mCall->hold(); + } emit backgrounded(); } else { @@ -77,7 +94,7 @@ void PhoneLine::incomming(const Call &call) { if(mCall) { - _debug("PhoneLine %d: Trying to set an incomming call to an active call.\n", mLine); + _debug("PhoneLine %d: Trying to set a phone line to an active call.\n", mLine); } else { mCall = new Call(call); @@ -173,3 +190,4 @@ PhoneLine::getCallId() return id; } + diff --git a/src/gui/official/PhoneLine.hpp b/src/gui/official/PhoneLine.hpp index 89166de8b..73814cdec 100644 --- a/src/gui/official/PhoneLine.hpp +++ b/src/gui/official/PhoneLine.hpp @@ -64,12 +64,21 @@ public slots: /** * The user selected this line. */ - void select(); + void select(bool hardselect = false); /** * This phoneline is no longer selected. */ - void unselect(); + void unselect(bool hardselect = false); + + /** + * This will do a hard unselect. it means it + * will remove the call if there's one. + */ + void disconnect(); + + void setState(const std::string &){} + void setPeer(const std::string &){} signals: diff --git a/src/gui/official/PhoneLineManagerImpl.cpp b/src/gui/official/PhoneLineManagerImpl.cpp index ef6c67e31..33aebe9e9 100644 --- a/src/gui/official/PhoneLineManagerImpl.cpp +++ b/src/gui/official/PhoneLineManagerImpl.cpp @@ -4,8 +4,9 @@ #include "globals.h" -#include "Call.hpp" -#include "Event.hpp" +#include "CallStatusFactory.hpp" +#include "SFLEvents.hpp" +#include "SFLCallStatus.hpp" #include "PhoneLine.hpp" #include "PhoneLineLocker.hpp" #include "PhoneLineManager.hpp" @@ -16,9 +17,22 @@ PhoneLineManagerImpl::PhoneLineManagerImpl() , mCurrentLine(NULL) , mIsInitialized(false) { - EventFactory::instance().registerEvent< HangupEvent >("002"); EventFactory::instance().registerEvent< IncommingEvent >("001"); + EventFactory::instance().registerEvent< HangupEvent >("002"); + EventFactory::instance().registerEvent< TryingStatus >("110"); + EventFactory::instance().registerEvent< RingingStatus >("111"); + EventFactory::instance().registerEvent< HoldStatus >("112"); + EventFactory::instance().registerEvent< EstablishedStatus >("113"); + EventFactory::instance().registerEvent< BusyStatus >("114"); + EventFactory::instance().registerEvent< CongestionStatus >("115"); + EventFactory::instance().registerEvent< WrongNumberStatus >("116"); + QObject::connect(this, SIGNAL(disconnected()), + this, SLOT(closeSession())); + QObject::connect(this, SIGNAL(readyToHandleEvents), + this, SLOT(handleEvents())); QObject::connect(this, SIGNAL(connected()), + this, SIGNAL(readyToSendStatus())); + QObject::connect(this, SIGNAL(readyToSendStatus()), this, SLOT(startSession())); } @@ -72,10 +86,37 @@ PhoneLineManagerImpl::startSession() { isInitialized(); + mSession->getCallStatus(); +} + +void +PhoneLineManagerImpl::handleEvents() +{ + isInitialized(); + mSession->getEvents(); } +void +PhoneLineManagerImpl::closeSession() +{ + isInitialized(); + + QMutexLocker guard(&mPhoneLinesMutex); + mCurrentLineMutex.lock(); + mCurrentLine = NULL; + mCurrentLineMutex.unlock(); + + unsigned int i = 0; + while(i < mPhoneLines.size()) { + PhoneLineLocker guard(mPhoneLines[i]); + mPhoneLines[i]->disconnect(); + i++; + } +} + + PhoneLine * PhoneLineManagerImpl::getCurrentLine() { @@ -90,6 +131,7 @@ PhoneLineManagerImpl::setNbLines(unsigned int nb) { isInitialized(); + QMutexLocker guard(&mPhoneLinesMutex); mPhoneLines.clear(); for(unsigned int i = 0; i < nb; i++) { mPhoneLines.push_back(new PhoneLine(*mSession, i + 1)); @@ -209,12 +251,39 @@ PhoneLineManagerImpl::sendKey(Qt::Key c) } +void +PhoneLineManagerImpl::selectLine(const std::string &callId, bool hardselect) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + mPhoneLinesMutex.lock(); + unsigned int line = 0; + while(!selectedLine && line < mPhoneLines.size()) { + if(mPhoneLines[line]->getCallId() == callId) { + selectedLine = mPhoneLines[line]; + } + else { + line++; + } + } + mPhoneLinesMutex.unlock(); + + if(selectedLine) { + selectLine(line, hardselect); + } + else { + _debug("PhoneLineManager: Tried to selected line with call ID (%s), " + "which appears to be invalid.\n", callId.c_str()); + } +} + /** * Warning: This function might 'cause a problem if * we select 2 line in a very short time. */ void -PhoneLineManagerImpl::selectLine(unsigned int line) +PhoneLineManagerImpl::selectLine(unsigned int line, bool hardselect) { isInitialized(); @@ -237,18 +306,18 @@ PhoneLineManagerImpl::selectLine(unsigned int line) if(oldLine != selectedLine) { if(oldLine != NULL) { PhoneLineLocker guard(oldLine); - oldLine->unselect(); + oldLine->unselect(hardselect); } PhoneLineLocker guard(selectedLine); - selectedLine->select(); + selectedLine->select(hardselect); if(selectedLine->isAvailable()) { mSession->playTone(); } } } else { - _debug("Tried to selected line %d, which appears to be invalid.\n", line); + _debug("PhoneLineManager: Tried to selected line %d, which appears to be invalid.\n", line); } } @@ -336,19 +405,38 @@ PhoneLineManagerImpl::clear() void PhoneLineManagerImpl::incomming(const std::string &, - const std::string &, + const std::string &peer, const std::string &callId) +{ + Call call(*mSession, callId, true); + addCall(call, peer, "Incomming"); +} + +void +PhoneLineManagerImpl::addCall(const std::string &, + const std::string &callId, + const std::string &peer, + const std::string &state) +{ + addCall(Call(*mSession, callId), peer, state); +} + +void +PhoneLineManagerImpl::addCall(Call call, + const std::string &peer, + const std::string &state) { PhoneLine *selectedLine = getNextAvailableLine(); PhoneLineLocker guard(selectedLine, false); - Call call(*mSession, callId, true); if(selectedLine) { selectedLine->incomming(call); + selectedLine->setPeer(peer); + selectedLine->setState(state); } else { - _debug("There's no available lines here for the incomming call ID: %s.\n", - callId.c_str()); + _debug("PhoneLineManager: There's no available lines here for the incomming call ID: %s.\n", + call.id().c_str()); call.notAvailable(); } } diff --git a/src/gui/official/PhoneLineManagerImpl.hpp b/src/gui/official/PhoneLineManagerImpl.hpp index ee2bed5fd..fc725f110 100644 --- a/src/gui/official/PhoneLineManagerImpl.hpp +++ b/src/gui/official/PhoneLineManagerImpl.hpp @@ -10,6 +10,7 @@ class PhoneLine; #include "Account.hpp" +#include "Call.hpp" #include "EventFactory.hpp" #include "Session.hpp" @@ -46,6 +47,9 @@ signals: void selected(unsigned int); void connected(); void disconnected(); + void readyToSendStatus(); + void readyToHandleEvents(); + void gotErrorOnCallStatus(); public slots: /** @@ -106,10 +110,25 @@ public slots: */ void call(const QString &to); + /** + * This function will add an incomming call + * on a phone line. + */ void incomming(const std::string &accountId, - const std::string &origin, - const std::string &callId); + const std::string &callId, + const std::string &peer); + /** + * This function is used to add a call on a + * phone line. + */ + void addCall(Call call, + const std::string &peer, + const std::string &state); + void addCall(const std::string &accountId, + const std::string &callId, + const std::string &peer, + const std::string &state); /** * This function will make a call on the @@ -124,7 +143,16 @@ public slots: * This function will switch the lines. If the line * is invalid, it just do nothing. */ - void selectLine(unsigned int line); + void selectLine(unsigned int line, + bool hardselect = false); + + /** + * This function will switch the line to the line having + * the given call id. If the line is invalid, it just do + * nothing. + */ + void selectLine(const std::string &callId, + bool hardselect = false); /** * This function will clear the buffer of the active @@ -144,6 +172,18 @@ public slots: */ PhoneLine *selectNextAvailableLine(); + /** + * This function will send the getevents request + * to the server. + * + * NOTE: This function MUST be called AFTER getcallstatus's + * completion. + */ + void handleEvents(); + + void errorOnCallStatus() + {emit gotErrorOnCallStatus();} + private slots: /** * This will send all the command needed when a @@ -151,6 +191,13 @@ public slots: */ void startSession(); + /** + * This function is called when we are disconnected + * from the server. This will unselect all phone lines. + */ + void closeSession(); + + private: void isInitialized(); diff --git a/src/gui/official/Request.cpp b/src/gui/official/Request.cpp index b95d60ab0..6ce4eea02 100644 --- a/src/gui/official/Request.cpp +++ b/src/gui/official/Request.cpp @@ -32,6 +32,20 @@ Request::Request(const std::string &sequenceId, , mArgs(args) {} +std::list< std::string > +Request::parseArgs(const std::string &message) +{ + std::istringstream stream(message); + std::string s; + std::list< std::string > args; + while(stream.good()) { + stream >> s; + args.push_back(s); + } + + return args; +} + void Request::onError(const std::string &code, const std::string &message) { diff --git a/src/gui/official/Request.hpp b/src/gui/official/Request.hpp index e35cc939b..c312249c1 100644 --- a/src/gui/official/Request.hpp +++ b/src/gui/official/Request.hpp @@ -37,6 +37,12 @@ class Request virtual ~Request(){} + /** + * This function will parse the message and will cut the message + * in many arguments. + */ + static std::list< std::string > parseArgs(const std::string &message); + /** * This function will be called when the request * receive its answer, if the request didn't successfully @@ -162,7 +168,6 @@ class AccountRequest : public Request const std::string &command, const std::list< std::string > &args); - /** * This function will be called when the request * receive its answer, if the request didn't successfully diff --git a/src/gui/official/SFLCallStatus.hpp b/src/gui/official/SFLCallStatus.hpp new file mode 100644 index 000000000..e322da49f --- /dev/null +++ b/src/gui/official/SFLCallStatus.hpp @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * + * + * 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 2 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. + */ + +#ifndef __SFLCALLSTATUS_HPP__ +#define __SFLCALLSTATUS_HPP__ + +#include "CallStatus.hpp" + + +typedef CallStatus TryingStatus; +typedef CallStatus RingingStatus; +typedef CallStatus HoldStatus; +typedef CallStatus EstablishedStatus; +typedef CallStatus BusyStatus; +typedef CallStatus CongestionStatus; +typedef CallStatus WrongNumberStatus; + +#endif diff --git a/src/gui/official/SFLEvents.cpp b/src/gui/official/SFLEvents.cpp new file mode 100644 index 000000000..70ac4c18b --- /dev/null +++ b/src/gui/official/SFLEvents.cpp @@ -0,0 +1,49 @@ +#include "globals.h" + +#include "PhoneLineManager.hpp" +#include "SFLEvents.hpp" + +HangupEvent::HangupEvent(const std::string &code, + const std::list< std::string > &args) + : CallRelatedEvent(code, args) +{} + +void +HangupEvent::execute() +{ + std::string id = getCallId(); + if(id.size() > 0) { + _debug("Hangup Event received for call ID: %s.\n", id.c_str()); + PhoneLineManager::instance().hangup(id); + } + else { + _debug("Hangup Event invalid (missing call ID): %s\n", toString().c_str()); + } +} + +IncommingEvent::IncommingEvent(const std::string &code, + const std::list< std::string > &args) + : CallRelatedEvent(code, args) +{ + std::list< std::string > l = getUnusedArgs(); + if(l.size() >= 3) { + mAccountId = *l.begin(); + l.pop_front(); + mOrigin = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +IncommingEvent::execute() +{ + std::string id = getCallId(); + if(id.size() > 0) { + _debug("Incomming Event received for call ID: %s.\n", id.c_str()); + PhoneLineManager::instance().incomming(mAccountId, getCallId(), mOrigin); + } + else { + _debug("Incomming Event invalid: %s\n", toString().c_str()); + } +} diff --git a/src/gui/official/SFLEvents.hpp b/src/gui/official/SFLEvents.hpp new file mode 100644 index 000000000..cd388c307 --- /dev/null +++ b/src/gui/official/SFLEvents.hpp @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * + * + * 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 2 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. + */ + +#ifndef __SFLEVENTS_HPP__ +#define __SFLEVENTS_HPP__ + +#include "Event.hpp" + +class HangupEvent : public CallRelatedEvent +{ +public: + HangupEvent(const std::string &code, + const std::list< std::string > &args); + + virtual void execute(); +}; + +class IncommingEvent : public CallRelatedEvent +{ +public: + IncommingEvent(const std::string &code, + const std::list< std::string > &args); + + virtual void execute(); + +private: + std::string mAccountId; + std::string mOrigin; +}; + + +#endif diff --git a/src/gui/official/SFLPhoneApp.cpp b/src/gui/official/SFLPhoneApp.cpp index 4e036a751..6e7b4b403 100644 --- a/src/gui/official/SFLPhoneApp.cpp +++ b/src/gui/official/SFLPhoneApp.cpp @@ -20,6 +20,7 @@ SFLPhoneApp::SFLPhoneApp(int argc, char **argv) Requester::instance().registerObject< Request >(std::string("playtone")); Requester::instance().registerObject< Request >(std::string("playdtmf")); Requester::instance().registerObject< EventRequest >(std::string("getevents")); + Requester::instance().registerObject< CallStatusRequest >(std::string("getcallstatus")); Requester::instance().registerObject< CallRelatedRequest >(std::string("answer")); Requester::instance().registerObject< CallRelatedRequest >(std::string("notavailable")); Requester::instance().registerObject< CallRelatedRequest >(std::string("refuse")); @@ -67,5 +68,11 @@ SFLPhoneApp::initConnections(SFLPhoneWindow *w) w, SLOT(askReconnect())); QObject::connect(w, SIGNAL(reconnectAsked()), &PhoneLineManager::instance(), SLOT(connect())); + + QObject::connect(&PhoneLineManager::instance(), SIGNAL(gotErrorOnCallStatus()), + w, SLOT(askResendStatus())); + QObject::connect(w, SIGNAL(resendStatusAsked), + &PhoneLineManager::instance(), SIGNAL(readyToSendStatus())); + } diff --git a/src/gui/official/SFLPhoneWindow.cpp b/src/gui/official/SFLPhoneWindow.cpp index 72496d606..12d1b38c0 100644 --- a/src/gui/official/SFLPhoneWindow.cpp +++ b/src/gui/official/SFLPhoneWindow.cpp @@ -107,7 +107,7 @@ SFLPhoneWindow::askReconnect() "Do you want to try to reconnect? If not, the application\n" "will close."), QMessageBox::Retry | QMessageBox::Default, - QMessageBox::Cancel | QMessageBox::Escape); + QMessageBox::No | QMessageBox::Escape); if (ret == QMessageBox::Retry) { emit reconnectAsked(); } @@ -115,3 +115,21 @@ SFLPhoneWindow::askReconnect() close(); } } + +void +SFLPhoneWindow::askResendStatus() +{ + int ret = QMessageBox::critical(NULL, + tr("SFLPhone status error"), + tr("The server returned an error for the lines status.\n" + "Do you want to try to resend this command? If not,\n" + "the application will close."), + QMessageBox::Retry | QMessageBox::Default, + QMessageBox::No | QMessageBox::Escape); + if (ret == QMessageBox::Retry) { + emit resendStatusAsked(); + } + else { + close(); + } +} diff --git a/src/gui/official/SFLPhoneWindow.hpp b/src/gui/official/SFLPhoneWindow.hpp index 72da6fd36..50a946aef 100644 --- a/src/gui/official/SFLPhoneWindow.hpp +++ b/src/gui/official/SFLPhoneWindow.hpp @@ -22,6 +22,7 @@ private: signals: void keyPressed(Qt::Key); void reconnectAsked(); + void resendStatusAsked(); public slots: /** @@ -30,6 +31,12 @@ signals: */ void askReconnect(); + /** + * This function will prompt a message box, to ask + * if the user want to resend the getcallstatus request. + */ + void askResendStatus(); + protected: void keyPressEvent(QKeyEvent *e); diff --git a/src/gui/official/SFLRequest.cpp b/src/gui/official/SFLRequest.cpp index 058d7090d..680ab17a6 100644 --- a/src/gui/official/SFLRequest.cpp +++ b/src/gui/official/SFLRequest.cpp @@ -5,6 +5,8 @@ #include "globals.h" #include "PhoneLineManager.hpp" #include "SFLRequest.hpp" +#include "CallStatus.hpp" +#include "CallStatusFactory.hpp" EventRequest::EventRequest(const std::string &sequenceId, const std::string &command, @@ -16,25 +18,57 @@ EventRequest::EventRequest(const std::string &sequenceId, void EventRequest::onError(const std::string &code, const std::string &message) { - _debug("EventRequest error: (%s) %s", code.c_str(), message.c_str()); + _debug("EventRequest error: (%s)%s\n", code.c_str(), message.c_str()); } void EventRequest::onEntry(const std::string &code, const std::string &message) { - std::istringstream stream(message); - std::string s; - std::list< std::string > args; - while(stream.good()) { - stream >> s; - args.push_back(s); - } - std::auto_ptr< Event > e(EventFactory::instance().create(code, args)); + std::auto_ptr< Event > + e(EventFactory::instance().create(code, Request::parseArgs(message))); e->execute(); } void EventRequest::onSuccess(const std::string &code, const std::string &message) { - _debug("EventRequest success: (%s) %s", code.c_str(), message.c_str()); + _debug("EventRequest success: (%s)%s\n", code.c_str(), message.c_str()); +} + +CallStatusRequest::CallStatusRequest(const std::string &sequenceId, + const std::string &command, + const std::list< std::string > &args) + : Request(sequenceId, command, args) +{} + + +void +CallStatusRequest::onError(const std::string &code, const std::string &message) +{ + _debug("CallStatusRequest error: (%s)%s\n", code.c_str(), message.c_str()); + PhoneLineManager::instance().errorOnCallStatus(); +} + +void +CallStatusRequest::onEntry(const std::string &code, const std::string &message) +{ + std::auto_ptr< Event > + e(EventFactory::instance().create(code, Request::parseArgs(message))); + e->execute(); +} + +void +CallStatusRequest::onSuccess(const std::string &code, const std::string &message) +{ + _debug("CallStatusRequest success: (%s)%s\n", code.c_str(), message.c_str()); + if(code == "206") { + std::list< std::string > args = Request::parseArgs(message); + if(args.size() >= 2) { + PhoneLineManager::instance().selectLine(*args.begin()); + } + else { + _debug("CallStatusRequest Error: cannot get current line.\n"); + } + } + PhoneLineManager::instance().handleEvents(); } diff --git a/src/gui/official/SFLRequest.hpp b/src/gui/official/SFLRequest.hpp index 51a2f1735..c2e483ae4 100644 --- a/src/gui/official/SFLRequest.hpp +++ b/src/gui/official/SFLRequest.hpp @@ -41,4 +41,39 @@ public: }; +class CallStatusRequest : public Request +{ +public: + CallStatusRequest(const std::string &sequenceId, + const std::string &command, + const std::list< std::string > &args); + + + virtual ~CallStatusRequest(){} + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. When we have an error on an EventRequest, we should + * quit the program. + */ + virtual void onError(const std::string &code, const std::string &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + * This will be dispatched to the valid event. + */ + virtual void onEntry(const std::string &code, const std::string &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. The event handling is gone, so we should + * quit. + */ + virtual void onSuccess(const std::string &code, const std::string &message); + +}; + #endif diff --git a/src/gui/official/Session.cpp b/src/gui/official/Session.cpp index 29f3d7fcf..4904f774d 100644 --- a/src/gui/official/Session.cpp +++ b/src/gui/official/Session.cpp @@ -62,6 +62,12 @@ Session::getEvents() const return Requester::instance().send(mId, "getevents", std::list< std::string >()); } +std::string +Session::getCallStatus() const +{ + return Requester::instance().send(mId, "getcallstatus", std::list< std::string >()); +} + std::string Session::playDtmf(char c) const { diff --git a/src/gui/official/Session.hpp b/src/gui/official/Session.hpp index 5f2c20f16..0edd24230 100644 --- a/src/gui/official/Session.hpp +++ b/src/gui/official/Session.hpp @@ -49,6 +49,11 @@ class Session */ std::string getEvents() const; + /** + * This function will ask for all calls status. + */ + std::string getCallStatus() const; + /** * This function will ask to the SessionIO * linked to this session to connect. diff --git a/src/gui/official/sflphone.pro b/src/gui/official/sflphone.pro index 64a5b00ce..2e4abc649 100644 --- a/src/gui/official/sflphone.pro +++ b/src/gui/official/sflphone.pro @@ -12,6 +12,8 @@ QT += network # Input HEADERS += Account.hpp \ Call.hpp \ + CallStatus.hpp \ + CallStatusFactory.hpp \ Event.hpp \ EventFactory.hpp EventFactory.inl \ Factory.hpp Factory.inl \ @@ -30,6 +32,7 @@ HEADERS += Account.hpp \ Session.hpp \ SessionIO.hpp \ SessionIOFactory.hpp \ + SFLEvents.hpp \ SFLPhoneApp.hpp \ SFLPhoneWindow.hpp \ SFLRequest.hpp \ @@ -42,6 +45,7 @@ HEADERS += Account.hpp \ FORMS += SFLPhoneWindow.ui SOURCES += Account.cpp \ Call.cpp \ + CallStatus.cpp \ Event.cpp \ JPushButton.cpp \ main.cpp \ @@ -52,6 +56,7 @@ SOURCES += Account.cpp \ Request.cpp \ RequesterImpl.cpp \ Session.cpp \ + SFLEvents.cpp \ SFLPhoneApp.cpp \ SFLPhoneWindow.cpp \ SFLRequest.cpp \