~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to kde/src/lib/call.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
 
 *   Copyright (C) 2009-2013 by Savoir-Faire Linux                          *
 
2
 *   Copyright (C) 2009-2014 by Savoir-Faire Linux                          *
3
3
 *   Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com>          *
4
4
 *            Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
5
5
 *                                                                          *
20
20
//Parent
21
21
#include "call.h"
22
22
 
 
23
//C include
 
24
#include <time.h>
 
25
 
23
26
//Qt
24
 
#include <QFile>
 
27
#include <QtCore/QFile>
 
28
#include <QtCore/QTimer>
 
29
 
25
30
 
26
31
//SFLPhone library
27
 
#include "callmanager_interface_singleton.h"
28
 
#include "configurationmanager_interface_singleton.h"
29
 
#include "contactbackend.h"
 
32
#include "dbus/callmanager.h"
 
33
#include "dbus/configurationmanager.h"
 
34
#include "abstractcontactbackend.h"
30
35
#include "contact.h"
31
36
#include "account.h"
32
 
#include "accountlist.h"
 
37
#include "accountlistmodel.h"
33
38
#include "videomodel.h"
 
39
#include "historymodel.h"
34
40
#include "instantmessagingmodel.h"
35
 
 
36
 
 
37
 
const call_state Call::actionPerformedStateMap [13][5] =
38
 
{
39
 
//                      ACCEPT                  REFUSE                  TRANSFER                   HOLD                           RECORD            /**/
40
 
/*INCOMING     */  {CALL_STATE_INCOMING   , CALL_STATE_INCOMING    , CALL_STATE_ERROR        , CALL_STATE_INCOMING     ,  CALL_STATE_INCOMING     },/**/
41
 
/*RINGING      */  {CALL_STATE_ERROR      , CALL_STATE_RINGING     , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_RINGING      },/**/
42
 
/*CURRENT      */  {CALL_STATE_ERROR      , CALL_STATE_CURRENT     , CALL_STATE_TRANSFERRED  , CALL_STATE_CURRENT      ,  CALL_STATE_CURRENT      },/**/
43
 
/*DIALING      */  {CALL_STATE_DIALING    , CALL_STATE_OVER        , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_ERROR        },/**/
44
 
/*HOLD         */  {CALL_STATE_ERROR      , CALL_STATE_HOLD        , CALL_STATE_TRANSF_HOLD  , CALL_STATE_HOLD         ,  CALL_STATE_HOLD         },/**/
45
 
/*FAILURE      */  {CALL_STATE_ERROR      , CALL_STATE_FAILURE     , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_ERROR        },/**/
46
 
/*BUSY         */  {CALL_STATE_ERROR      , CALL_STATE_BUSY        , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_ERROR        },/**/
47
 
/*TRANSFER     */  {CALL_STATE_TRANSFERRED, CALL_STATE_TRANSFERRED , CALL_STATE_CURRENT      , CALL_STATE_TRANSFERRED  ,  CALL_STATE_TRANSFERRED  },/**/
48
 
/*TRANSF_HOLD  */  {CALL_STATE_TRANSF_HOLD, CALL_STATE_TRANSF_HOLD , CALL_STATE_HOLD         , CALL_STATE_TRANSF_HOLD  ,  CALL_STATE_TRANSF_HOLD  },/**/
49
 
/*OVER         */  {CALL_STATE_ERROR      , CALL_STATE_ERROR       , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_ERROR        },/**/
50
 
/*ERROR        */  {CALL_STATE_ERROR      , CALL_STATE_ERROR       , CALL_STATE_ERROR        , CALL_STATE_ERROR        ,  CALL_STATE_ERROR        },/**/
51
 
/*CONF         */  {CALL_STATE_ERROR      , CALL_STATE_CURRENT     , CALL_STATE_TRANSFERRED  , CALL_STATE_CURRENT      ,  CALL_STATE_CURRENT      },/**/
52
 
/*CONF_HOLD    */  {CALL_STATE_ERROR      , CALL_STATE_HOLD        , CALL_STATE_TRANSF_HOLD  , CALL_STATE_HOLD         ,  CALL_STATE_HOLD         },/**/
53
 
};//                                                                                                                                                    
54
 
 
55
 
 
56
 
const function Call::actionPerformedFunctionMap[13][5] =
57
 
58
 
//                      ACCEPT               REFUSE            TRANSFER                 HOLD                  RECORD             /**/
59
 
/*INCOMING       */  {&Call::accept     , &Call::refuse   , &Call::acceptTransf   , &Call::acceptHold  ,  &Call::setRecord     },/**/
60
 
/*RINGING        */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::setRecord     },/**/
61
 
/*CURRENT        */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     },/**/
62
 
/*DIALING        */  {&Call::call       , &Call::cancel   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       },/**/
63
 
/*HOLD           */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     },/**/
64
 
/*FAILURE        */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       },/**/
65
 
/*BUSY           */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       },/**/
66
 
/*TRANSFERT      */  {&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::hold        ,  &Call::setRecord     },/**/
67
 
/*TRANSFERT_HOLD */  {&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::unhold      ,  &Call::setRecord     },/**/
68
 
/*OVER           */  {&Call::nothing    , &Call::nothing  , &Call::nothing        , &Call::nothing     ,  &Call::nothing       },/**/
69
 
/*ERROR          */  {&Call::nothing    , &Call::nothing  , &Call::nothing        , &Call::nothing     ,  &Call::nothing       },/**/
70
 
/*CONF           */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     },/**/
71
 
/*CONF_HOLD      */  {&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     },/**/
72
 
};//                                                                                                                                 
73
 
 
74
 
 
75
 
const call_state Call::stateChangedStateMap [13][6] =
76
 
{
77
 
//                      RINGING                  CURRENT                BUSY                HOLD                        HUNGUP           FAILURE             /**/
78
 
/*INCOMING     */ {CALL_STATE_INCOMING    , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
79
 
/*RINGING      */ {CALL_STATE_RINGING     , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
80
 
/*CURRENT      */ {CALL_STATE_CURRENT     , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
81
 
/*DIALING      */ {CALL_STATE_RINGING     , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
82
 
/*HOLD         */ {CALL_STATE_HOLD        , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
83
 
/*FAILURE      */ {CALL_STATE_FAILURE     , CALL_STATE_FAILURE    , CALL_STATE_BUSY   , CALL_STATE_FAILURE      ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
84
 
/*BUSY         */ {CALL_STATE_BUSY        , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_BUSY         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
85
 
/*TRANSFER     */ {CALL_STATE_TRANSFERRED , CALL_STATE_TRANSFERRED, CALL_STATE_BUSY   , CALL_STATE_TRANSF_HOLD  ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
86
 
/*TRANSF_HOLD  */ {CALL_STATE_TRANSF_HOLD , CALL_STATE_TRANSFERRED, CALL_STATE_BUSY   , CALL_STATE_TRANSF_HOLD  ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
87
 
/*OVER         */ {CALL_STATE_OVER        , CALL_STATE_OVER       , CALL_STATE_OVER   , CALL_STATE_OVER         ,  CALL_STATE_OVER  ,  CALL_STATE_OVER     },/**/
88
 
/*ERROR        */ {CALL_STATE_ERROR       , CALL_STATE_ERROR      , CALL_STATE_ERROR  , CALL_STATE_ERROR        ,  CALL_STATE_ERROR ,  CALL_STATE_ERROR    },/**/
89
 
/*CONF         */ {CALL_STATE_CURRENT     , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
90
 
/*CONF_HOLD    */ {CALL_STATE_HOLD        , CALL_STATE_CURRENT    , CALL_STATE_BUSY   , CALL_STATE_HOLD         ,  CALL_STATE_OVER  ,  CALL_STATE_FAILURE  },/**/
91
 
};//                                                                                                                                                             
92
 
 
93
 
const function Call::stateChangedFunctionMap[13][6] =
94
 
 
41
#include "useractionmodel.h"
 
42
#include "callmodel.h"
 
43
#include "numbercategory.h"
 
44
#include "phonedirectorymodel.h"
 
45
#include "phonenumber.h"
 
46
#include "videorenderer.h"
 
47
#include "tlsmethodmodel.h"
 
48
#include "audiosettingsmodel.h"
 
49
 
 
50
const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call::State> Call::actionPerformedStateMap =
 
51
{{
 
52
//                           ACCEPT                   REFUSE                  TRANSFER                       HOLD                           RECORD              /**/
 
53
/*INCOMING     */  {{Call::State::INCOMING   , Call::State::INCOMING    , Call::State::ERROR        , Call::State::INCOMING     ,  Call::State::INCOMING     }},/**/
 
54
/*RINGING      */  {{Call::State::ERROR      , Call::State::RINGING     , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::RINGING      }},/**/
 
55
/*CURRENT      */  {{Call::State::ERROR      , Call::State::CURRENT     , Call::State::TRANSFERRED  , Call::State::CURRENT      ,  Call::State::CURRENT      }},/**/
 
56
/*DIALING      */  {{Call::State::DIALING    , Call::State::OVER        , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
 
57
/*HOLD         */  {{Call::State::ERROR      , Call::State::HOLD        , Call::State::TRANSF_HOLD  , Call::State::HOLD         ,  Call::State::HOLD         }},/**/
 
58
/*FAILURE      */  {{Call::State::ERROR      , Call::State::FAILURE     , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
 
59
/*BUSY         */  {{Call::State::ERROR      , Call::State::BUSY        , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
 
60
/*TRANSFER     */  {{Call::State::TRANSFERRED, Call::State::TRANSFERRED , Call::State::CURRENT      , Call::State::TRANSFERRED  ,  Call::State::TRANSFERRED  }},/**/
 
61
/*TRANSF_HOLD  */  {{Call::State::TRANSF_HOLD, Call::State::TRANSF_HOLD , Call::State::HOLD         , Call::State::TRANSF_HOLD  ,  Call::State::TRANSF_HOLD  }},/**/
 
62
/*OVER         */  {{Call::State::ERROR      , Call::State::ERROR       , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
 
63
/*ERROR        */  {{Call::State::ERROR      , Call::State::ERROR       , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
 
64
/*CONF         */  {{Call::State::ERROR      , Call::State::CURRENT     , Call::State::TRANSFERRED  , Call::State::CURRENT      ,  Call::State::CURRENT      }},/**/
 
65
/*CONF_HOLD    */  {{Call::State::ERROR      , Call::State::HOLD        , Call::State::TRANSF_HOLD  , Call::State::HOLD         ,  Call::State::HOLD         }},/**/
 
66
}};//                                                                                                                                                    
 
67
 
 
68
 
 
69
const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > Call::actionPerformedFunctionMap =
 
70
{{
 
71
//                        ACCEPT               REFUSE            TRANSFER                 HOLD                  RECORD             /**/
 
72
/*INCOMING       */  {{&Call::accept     , &Call::refuse   , &Call::acceptTransf   , &Call::acceptHold  ,  &Call::setRecord     }},/**/
 
73
/*RINGING        */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::setRecord     }},/**/
 
74
/*CURRENT        */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     }},/**/
 
75
/*DIALING        */  {{&Call::call       , &Call::cancel   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
 
76
/*HOLD           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     }},/**/
 
77
/*FAILURE        */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
 
78
/*BUSY           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
 
79
/*TRANSFERT      */  {{&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::hold        ,  &Call::setRecord     }},/**/
 
80
/*TRANSFERT_HOLD */  {{&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::unhold      ,  &Call::setRecord     }},/**/
 
81
/*OVER           */  {{&Call::nothing    , &Call::nothing  , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
 
82
/*ERROR          */  {{&Call::nothing    , &Call::remove   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
 
83
/*CONF           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     }},/**/
 
84
/*CONF_HOLD      */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     }},/**/
 
85
}};//                                                                                                                                 
 
86
 
 
87
 
 
88
const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState> , Call::State> Call::stateChangedStateMap =
 
89
{{
 
90
//                        RINGING                   CURRENT                   BUSY                  HOLD                        HUNGUP                 FAILURE           /**/
 
91
/*INCOMING     */ {{Call::State::INCOMING    , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
92
/*RINGING      */ {{Call::State::RINGING     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
93
/*CURRENT      */ {{Call::State::CURRENT     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
94
/*DIALING      */ {{Call::State::RINGING     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
95
/*HOLD         */ {{Call::State::HOLD        , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
96
/*FAILURE      */ {{Call::State::FAILURE     , Call::State::FAILURE    , Call::State::BUSY   , Call::State::FAILURE      ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
97
/*BUSY         */ {{Call::State::BUSY        , Call::State::CURRENT    , Call::State::BUSY   , Call::State::BUSY         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
98
/*TRANSFER     */ {{Call::State::TRANSFERRED , Call::State::TRANSFERRED, Call::State::BUSY   , Call::State::TRANSF_HOLD  ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
99
/*TRANSF_HOLD  */ {{Call::State::TRANSF_HOLD , Call::State::TRANSFERRED, Call::State::BUSY   , Call::State::TRANSF_HOLD  ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
100
/*OVER         */ {{Call::State::OVER        , Call::State::OVER       , Call::State::OVER   , Call::State::OVER         ,  Call::State::OVER  ,  Call::State::OVER     }},/**/
 
101
/*ERROR        */ {{Call::State::ERROR       , Call::State::ERROR      , Call::State::ERROR  , Call::State::ERROR        ,  Call::State::ERROR ,  Call::State::ERROR    }},/**/
 
102
/*CONF         */ {{Call::State::CURRENT     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
103
/*CONF_HOLD    */ {{Call::State::HOLD        , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 
104
}};//                                                                                                                                                             
 
105
 
 
106
const TypedStateMachine< TypedStateMachine< function , Call::DaemonState > , Call::State > Call::stateChangedFunctionMap =
 
107
{{ 
95
108
//                      RINGING                  CURRENT             BUSY              HOLD                    HUNGUP           FAILURE            /**/
96
 
/*INCOMING       */  {&Call::nothing    , &Call::start     , &Call::startWeird     , &Call::startWeird   ,  &Call::startStop    , &Call::start   },/**/
97
 
/*RINGING        */  {&Call::nothing    , &Call::start     , &Call::start          , &Call::start        ,  &Call::startStop    , &Call::start   },/**/
98
 
/*CURRENT        */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
99
 
/*DIALING        */  {&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning },/**/
100
 
/*HOLD           */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
101
 
/*FAILURE        */  {&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::nothing },/**/
102
 
/*BUSY           */  {&Call::nothing    , &Call::nothing   , &Call::nothing        , &Call::warning      ,  &Call::stop         , &Call::nothing },/**/
103
 
/*TRANSFERT      */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
104
 
/*TRANSFERT_HOLD */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
105
 
/*OVER           */  {&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning },/**/
106
 
/*ERROR          */  {&Call::nothing    , &Call::nothing   , &Call::nothing        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
107
 
/*CONF           */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
108
 
/*CONF_HOLD      */  {&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing },/**/
109
 
};//                                                                                                                                                   
110
 
 
111
 
const char * Call::historyIcons[3] = {ICON_HISTORY_INCOMING, ICON_HISTORY_OUTGOING, ICON_HISTORY_MISSED};
112
 
 
113
 
ContactBackend* Call::m_pContactBackend = nullptr;
114
 
Call*           Call::m_sSelectedCall   = nullptr;
115
 
 
116
 
void Call::setContactBackend(ContactBackend* be)
 
109
/*INCOMING       */  {{&Call::nothing    , &Call::start     , &Call::startWeird     , &Call::startWeird   ,  &Call::startStop    , &Call::start   }},/**/
 
110
/*RINGING        */  {{&Call::nothing    , &Call::start     , &Call::start          , &Call::start        ,  &Call::startStop    , &Call::start   }},/**/
 
111
/*CURRENT        */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
112
/*DIALING        */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning }},/**/
 
113
/*HOLD           */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
114
/*FAILURE        */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::nothing }},/**/
 
115
/*BUSY           */  {{&Call::nothing    , &Call::nothing   , &Call::nothing        , &Call::warning      ,  &Call::stop         , &Call::nothing }},/**/
 
116
/*TRANSFERT      */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
117
/*TRANSFERT_HOLD */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
118
/*OVER           */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning }},/**/
 
119
/*ERROR          */  {{&Call::error      , &Call::error     , &Call::error          , &Call::error        ,  &Call::stop         , &Call::error   }},/**/
 
120
/*CONF           */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
121
/*CONF_HOLD      */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
 
122
}};//                                                                                                                                                   
 
123
 
 
124
QDebug LIB_EXPORT operator<<(QDebug dbg, const Call::State& c)
 
125
{
 
126
   dbg.nospace() << QString(Call::toHumanStateName(c));
 
127
   return dbg.space();
 
128
}
 
129
 
 
130
QDebug LIB_EXPORT operator<<(QDebug dbg, const Call::DaemonState& c)
 
131
{
 
132
   dbg.nospace() << static_cast<int>(c);
 
133
   return dbg.space();
 
134
}
 
135
 
 
136
QDebug LIB_EXPORT operator<<(QDebug dbg, const Call::Action& c)
 
137
{
 
138
   dbg.nospace() << static_cast<int>(c);
 
139
   return dbg.space();
 
140
}
 
141
 
 
142
AbstractContactBackend* Call::m_pContactBackend = nullptr;
 
143
Call*                   Call::m_sSelectedCall   = nullptr;
 
144
 
 
145
void Call::setContactBackend(AbstractContactBackend* be)
117
146
{
118
147
   m_pContactBackend = be;
119
148
}
120
149
 
 
150
AbstractContactBackend* Call::contactBackend ()
 
151
{
 
152
   return m_pContactBackend;
 
153
}
 
154
 
121
155
///Constructor
122
 
Call::Call(call_state startState, QString callId, QString peerName, QString peerNumber, QString account)
123
 
   : m_isConference(false),m_pStopTime(nullptr),m_pStartTime(nullptr),
124
 
   m_ContactChanged(false),m_pContact(nullptr),m_pImModel(nullptr)
 
156
Call::Call(Call::State startState, const QString& callId, const QString& peerName, PhoneNumber* number, Account* account)
 
157
   :  QObject(CallModel::instance()), m_isConference(false),m_pStopTimeStamp(0),
 
158
   m_pImModel(nullptr),m_pTimer(nullptr),m_Recording(false),m_Account(nullptr),
 
159
   m_PeerName(peerName),m_pPeerPhoneNumber(number),m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),
 
160
   m_CallId(callId),m_CurrentState(startState),m_pStartTimeStamp(0),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
 
161
   m_History(false),m_Missed(false),m_Direction(Call::Direction::OUTGOING)
125
162
{
126
 
   this->m_CallId          = callId     ;
127
 
   this->m_PeerPhoneNumber = peerNumber ;
128
 
   this->m_PeerName        = peerName   ;
129
 
   this->m_Account         = account    ;
130
 
   this->m_Recording       = false      ;
131
 
   this->m_pStartTime      = nullptr    ;
132
 
   this->m_pStopTime       = nullptr    ;
133
 
   changeCurrentState(startState)       ;
134
 
 
135
 
   m_ContactChanged = true;
136
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
137
 
   connect(&callManager,SIGNAL(recordPlaybackStopped(QString)), this, SLOT(stopPlayback(QString))  );
138
 
   connect(&callManager,SIGNAL(updatePlaybackScale(int,int))  , this, SLOT(updatePlayback(int,int)));
139
 
   if (m_pContactBackend)
140
 
      connect(m_pContactBackend,SIGNAL(collectionChanged()),this,SLOT(contactBackendChanged()));
 
163
   m_Account = account;
 
164
   Q_ASSERT(!callId.isEmpty());
 
165
   setObjectName("Call:"+callId);
 
166
   changeCurrentState(startState);
 
167
   m_pUserActionModel = new UserActionModel(this);
141
168
 
142
169
   emit changed();
143
170
   emit changed(this);
146
173
///Destructor
147
174
Call::~Call()
148
175
{
149
 
   //if (m_pStartTime) delete m_pStartTime ;
150
 
   //if (m_pStopTime)  delete m_pStopTime  ;
 
176
   if (m_pTimer) delete m_pTimer;
151
177
   this->disconnect();
 
178
   if ( m_pTransferNumber ) delete m_pTransferNumber;
 
179
   if ( m_pDialNumber     ) delete m_pDialNumber;
152
180
}
153
181
 
154
182
///Constructor
155
 
Call::Call(QString confId, QString account): m_isConference(false),m_pStopTime(nullptr),m_pStartTime(nullptr),
156
 
   m_ContactChanged(false),m_pContact(nullptr),m_pImModel(nullptr)
 
183
Call::Call(const QString& confId, const QString& account): QObject(CallModel::instance()),
 
184
   m_pStopTimeStamp(0),m_pStartTimeStamp(0),m_pImModel(nullptr),m_ConfId(confId),
 
185
   m_Account(AccountListModel::instance()->getAccountById(account)),m_CurrentState(Call::State::CONFERENCE),
 
186
   m_pTimer(nullptr), m_isConference(false),m_pPeerPhoneNumber(nullptr),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
 
187
   m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),m_History(false),m_Missed(false),
 
188
   m_Direction(Call::Direction::OUTGOING)
157
189
{
158
 
   m_isConference  = m_ConfId.isEmpty();
159
 
   this->m_ConfId  = confId  ;
160
 
   this->m_Account = account ;
 
190
   setObjectName("Conf:"+confId);
 
191
   m_isConference  = !m_ConfId.isEmpty();
 
192
   m_pUserActionModel = new UserActionModel(this);
161
193
 
162
194
   if (m_isConference) {
163
 
      CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
195
      time_t curTime;
 
196
      ::time(&curTime);
 
197
      setStartTimeStamp(curTime);
 
198
      m_pTimer = new QTimer(this);
 
199
      m_pTimer->setInterval(1000);
 
200
      connect(m_pTimer,SIGNAL(timeout()),this,SLOT(updated()));
 
201
      m_pTimer->start();
 
202
      CallManagerInterface& callManager = DBus::CallManager::instance();
164
203
      MapStringString        details    = callManager.getConferenceDetails(m_ConfId)  ;
165
204
      m_CurrentState = confStatetoCallState(details["CONF_STATE"]);
 
205
      emit stateChanged();
166
206
   }
167
207
}
168
208
 
175
215
///Build a call from its ID
176
216
Call* Call::buildExistingCall(QString callId)
177
217
{
178
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
218
   CallManagerInterface& callManager = DBus::CallManager::instance();
179
219
   MapStringString       details     = callManager.getCallDetails(callId).value();
180
220
 
181
 
   qDebug() << "Constructing existing call with details : " << details;
182
 
 
183
 
   QString    peerNumber = details[ CALL_PEER_NUMBER ];
184
 
   QString    peerName   = details[ CALL_PEER_NAME   ];
185
 
   QString    account    = details[ CALL_ACCOUNTID   ];
186
 
   call_state startState = getStartStateFromDaemonCallState(details[CALL_STATE], details[CALL_TYPE]);
187
 
 
188
 
   Call* call            = new Call(startState, callId, peerName, peerNumber, account)                   ;
189
 
 
190
 
   if (!details[ CALL_TIMESTAMP_START ].isEmpty())
191
 
      call->m_pStartTime = new QDateTime(QDateTime::fromTime_t(details[ CALL_TIMESTAMP_START ].toInt())) ;
192
 
   else
193
 
      call->m_pStartTime = new QDateTime(QDateTime::currentDateTime())                                   ;
194
 
 
195
 
   call->m_Recording     = callManager.getIsRecording(callId)                                            ;
196
 
   call->m_HistoryState  = getHistoryStateFromType(details[STATE_KEY]);
 
221
   //Too noisy
 
222
   //qDebug() << "Constructing existing call with details : " << details;
 
223
 
 
224
   const QString peerNumber  = details[ Call::DetailsMapFields::PEER_NUMBER ];
 
225
   const QString peerName    = details[ Call::DetailsMapFields::PEER_NAME   ];
 
226
   const QString account     = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
 
227
   Call::State   startState  = startStateFromDaemonCallState(details[Call::DetailsMapFields::STATE], details[Call::DetailsMapFields::TYPE]);
 
228
   Account*      acc         = AccountListModel::instance()->getAccountById(account);
 
229
   PhoneNumber*  nb          = PhoneDirectoryModel::instance()->getNumber(peerNumber,acc);
 
230
   Call*         call        = new Call(startState, callId, peerName, nb, acc);
 
231
   call->m_Recording      = callManager.getIsRecording(callId);
 
232
   call->m_HistoryState   = historyStateFromType(details[Call::HistoryMapFields::STATE]);
 
233
 
 
234
   if (!details[ Call::DetailsMapFields::TIMESTAMP_START ].isEmpty())
 
235
      call->setStartTimeStamp(details[ Call::DetailsMapFields::TIMESTAMP_START ].toInt());
 
236
   else {
 
237
      time_t curTime;
 
238
      ::time(&curTime);
 
239
      call->setStartTimeStamp(curTime);
 
240
   }
 
241
 
 
242
 
 
243
   call->m_pTimer = new QTimer(CallModel::instance());
 
244
   call->m_pTimer->setInterval(1000);
 
245
   connect(call->m_pTimer,SIGNAL(timeout()),call,SLOT(updated()));
 
246
   call->m_pTimer->start();
 
247
 
 
248
   if (call->peerPhoneNumber()) {
 
249
      call->peerPhoneNumber()->addCall(call);
 
250
   }
197
251
 
198
252
   return call;
199
253
} //buildExistingCall
200
254
 
201
255
///Build a call from a dialing call (a call that is about to exist)
202
 
Call* Call::buildDialingCall(QString callId, const QString & peerName, QString account)
 
256
Call* Call::buildDialingCall(const QString& callId, const QString & peerName, Account* account)
203
257
{
204
 
   Call* call = new Call(CALL_STATE_DIALING, callId, peerName, "", account);
205
 
   call->m_HistoryState = NONE;
 
258
   Call* call = new Call(Call::State::DIALING, callId, peerName, nullptr, account);
 
259
   call->m_HistoryState = Call::LegacyHistoryState::NONE;
 
260
   call->m_Direction = Call::Direction::OUTGOING;
 
261
   if (AudioSettingsModel::instance()->isRoomToneEnabled()) {
 
262
      AudioSettingsModel::instance()->playRoomTone();
 
263
   }
206
264
   return call;
207
265
}
208
266
 
209
267
///Build a call from a dbus event
210
 
Call* Call::buildIncomingCall(const QString & callId)
 
268
Call* Call::buildIncomingCall(const QString& callId)
211
269
{
212
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
270
   CallManagerInterface & callManager = DBus::CallManager::instance();
213
271
   MapStringString details = callManager.getCallDetails(callId).value();
214
272
 
215
 
   QString from     = details[ CALL_PEER_NUMBER ];
216
 
   QString account  = details[ CALL_ACCOUNTID   ];
217
 
   QString peerName = details[ CALL_PEER_NAME   ];
218
 
   
219
 
   Call* call = new Call(CALL_STATE_INCOMING, callId, peerName, from, account);
220
 
   call->m_HistoryState = MISSED;
 
273
   const QString from     = details[ Call::DetailsMapFields::PEER_NUMBER ];
 
274
   const QString account  = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
 
275
   const QString peerName = details[ Call::DetailsMapFields::PEER_NAME   ];
 
276
   Account*      acc      = AccountListModel::instance()->getAccountById(account);
 
277
   PhoneNumber*  nb       = PhoneDirectoryModel::instance()->getNumber(from,acc);
 
278
   Call* call = new Call(Call::State::INCOMING, callId, peerName, nb, acc);
 
279
   call->m_HistoryState   = Call::LegacyHistoryState::MISSED;
 
280
   call->m_Direction      = Call::Direction::INCOMING;
 
281
   if (call->peerPhoneNumber()) {
 
282
      call->peerPhoneNumber()->addCall(call);
 
283
   }
221
284
   return call;
222
285
} //buildIncomingCall
223
286
 
224
 
///Build a rigging call (from dbus)
 
287
///Build a ringing call (from dbus)
225
288
Call* Call::buildRingingCall(const QString & callId)
226
289
{
227
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
290
   CallManagerInterface& callManager = DBus::CallManager::instance();
228
291
   MapStringString details = callManager.getCallDetails(callId).value();
229
 
   
230
 
   QString from     = details[ CALL_PEER_NUMBER ];
231
 
   QString account  = details[ CALL_ACCOUNTID   ];
232
 
   QString peerName = details[ CALL_PEER_NAME   ];
233
 
   
234
 
   Call* call = new Call(CALL_STATE_RINGING, callId, peerName, from, account);
235
 
   call->m_HistoryState = OUTGOING;
 
292
 
 
293
   const QString from     = details[ Call::DetailsMapFields::PEER_NUMBER ];
 
294
   const QString account  = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
 
295
   const QString peerName = details[ Call::DetailsMapFields::PEER_NAME   ];
 
296
   Account*      acc      = AccountListModel::instance()->getAccountById(account);
 
297
   PhoneNumber*  nb       = PhoneDirectoryModel::instance()->getNumber(from,acc);
 
298
 
 
299
   Call* call = new Call(Call::State::RINGING, callId, peerName, nb, acc);
 
300
   call->m_HistoryState = LegacyHistoryState::OUTGOING;
 
301
   call->m_Direction    = Call::Direction::OUTGOING;
 
302
 
 
303
   if (call->peerPhoneNumber()) {
 
304
      call->peerPhoneNumber()->addCall(call);
 
305
   }
236
306
   return call;
237
307
} //buildRingingCall
238
308
 
 
309
 
239
310
/*****************************************************************************
240
311
 *                                                                           *
241
312
 *                                  History                                  *
243
314
 ****************************************************************************/
244
315
 
245
316
///Build a call that is already over
246
 
Call* Call::buildHistoryCall(const QString & callId, uint startTimeStamp, uint stopTimeStamp, QString account, QString name, QString number, QString type)
 
317
Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
247
318
{
248
 
   if(name == "empty") name = "";
249
 
   Call* call            = new Call(CALL_STATE_OVER, callId, name, number, account );
250
 
 
251
 
   QDateTime* start = new QDateTime(QDateTime::fromTime_t(startTimeStamp));
252
 
   QDateTime* stop  = new QDateTime(QDateTime::fromTime_t(stopTimeStamp));
253
 
 
254
 
   if (start){
255
 
      call->m_pStartTime = start;
256
 
      call->m_pStopTime  = stop;
257
 
   }
258
 
   
259
 
   call->m_HistoryState  = getHistoryStateFromType(type);
260
 
   
 
319
   const QString& callId          = hc[ Call::HistoryMapFields::CALLID          ]          ;
 
320
   time_t         startTimeStamp  = hc[ Call::HistoryMapFields::TIMESTAMP_START ].toUInt() ;
 
321
   time_t         stopTimeStamp   = hc[ Call::HistoryMapFields::TIMESTAMP_STOP  ].toUInt() ;
 
322
   const QString& accId           = hc[ Call::HistoryMapFields::ACCOUNT_ID      ]          ;
 
323
   const QString& name            = hc[ Call::HistoryMapFields::DISPLAY_NAME    ]          ;
 
324
   const QString& number          = hc[ Call::HistoryMapFields::PEER_NUMBER     ]          ;
 
325
   const QString& type            = hc[ Call::HistoryMapFields::STATE           ]          ;
 
326
   const QString& direction       = hc[ Call::HistoryMapFields::DIRECTION       ]          ;
 
327
   const bool     missed          = hc[ Call::HistoryMapFields::MISSED          ] == "true";
 
328
 
 
329
   Account*      acc       = AccountListModel::instance()->getAccountById(accId);
 
330
   PhoneNumber*  nb        = PhoneDirectoryModel::instance()->getNumber(number,acc);
 
331
   Call*         call      = new Call(Call::State::OVER, callId, (name == "empty")?QString():name, nb, acc );
 
332
 
 
333
   call->m_pStopTimeStamp  = stopTimeStamp ;
 
334
   call->m_History         = true;
 
335
   call->setStartTimeStamp(startTimeStamp);
 
336
 
 
337
   call->m_HistoryState    = historyStateFromType(type);
 
338
   call->m_Account         = AccountListModel::instance()->getAccountById(accId);
 
339
 
 
340
   //BEGIN In ~2015, remove the old logic and clean this
 
341
   if (missed || call->m_HistoryState == Call::LegacyHistoryState::MISSED) {
 
342
      call->m_Missed = true;
 
343
      call->m_HistoryState = Call::LegacyHistoryState::MISSED;
 
344
   }
 
345
   if (!direction.isEmpty()) {
 
346
      if (direction == HistoryStateName::INCOMING) {
 
347
         call->m_Direction    = Call::Direction::INCOMING         ;
 
348
         call->m_HistoryState = Call::LegacyHistoryState::INCOMING;
 
349
      }
 
350
      else if (direction == HistoryStateName::OUTGOING) {
 
351
         call->m_Direction    = Call::Direction::OUTGOING         ;
 
352
         call->m_HistoryState = Call::LegacyHistoryState::OUTGOING;
 
353
      }
 
354
   }
 
355
   else if (call->m_HistoryState == Call::LegacyHistoryState::INCOMING)
 
356
      call->m_Direction    = Call::Direction::INCOMING            ;
 
357
   else if (call->m_HistoryState == Call::LegacyHistoryState::OUTGOING)
 
358
      call->m_Direction    = Call::Direction::OUTGOING            ;
 
359
   else //BUG Pick one, even if it is the wrong one
 
360
      call->m_Direction    = Call::Direction::OUTGOING            ;
 
361
   if (missed)
 
362
      call->m_HistoryState = Call::LegacyHistoryState::MISSED;
 
363
   //END
 
364
 
 
365
   call->setObjectName("History:"+call->m_CallId);
 
366
 
 
367
   if (call->peerPhoneNumber()) {
 
368
      call->peerPhoneNumber()->addCall(call);
 
369
      connect(call->peerPhoneNumber(),SIGNAL(presentChanged(bool)),call,SLOT(updated()));
 
370
   }
 
371
 
261
372
   return call;
262
373
}
263
374
 
264
375
///Get the history state from the type (see Call.cpp header)
265
 
history_state Call::getHistoryStateFromType(QString type)
 
376
Call::LegacyHistoryState Call::historyStateFromType(const QString& type)
266
377
{
267
 
   if(type == MISSED_STRING        )
268
 
      return MISSED   ;
269
 
   else if(type == OUTGOING_STRING )
270
 
      return OUTGOING ;
271
 
   else if(type == INCOMING_STRING )
272
 
      return INCOMING ;
273
 
   return NONE        ;
 
378
   if(type == Call::HistoryStateName::MISSED        )
 
379
      return Call::LegacyHistoryState::MISSED   ;
 
380
   else if(type == Call::HistoryStateName::OUTGOING )
 
381
      return Call::LegacyHistoryState::OUTGOING ;
 
382
   else if(type == Call::HistoryStateName::INCOMING )
 
383
      return Call::LegacyHistoryState::INCOMING ;
 
384
   return  Call::LegacyHistoryState::NONE       ;
274
385
}
275
386
 
276
387
///Get the start sate from the daemon state
277
 
call_state Call::getStartStateFromDaemonCallState(QString daemonCallState, QString daemonCallType)
 
388
Call::State Call::startStateFromDaemonCallState(const QString& daemonCallState, const QString& daemonCallType)
278
389
{
279
 
   if(daemonCallState      == DAEMON_CALL_STATE_INIT_CURRENT  )
280
 
      return CALL_STATE_CURRENT  ;
281
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_HOLD     )
282
 
      return CALL_STATE_HOLD     ;
283
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_BUSY     )
284
 
      return CALL_STATE_BUSY     ;
285
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_INACTIVE && daemonCallType == DAEMON_CALL_TYPE_INCOMING )
286
 
      return CALL_STATE_INCOMING ;
287
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_INACTIVE && daemonCallType == DAEMON_CALL_TYPE_OUTGOING )
288
 
      return CALL_STATE_RINGING  ;
289
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_INCOMING )
290
 
      return CALL_STATE_INCOMING ;
291
 
   else if(daemonCallState == DAEMON_CALL_STATE_INIT_RINGING  )
292
 
      return CALL_STATE_RINGING  ;
 
390
   if(daemonCallState      == Call::DaemonStateInit::CURRENT  )
 
391
      return Call::State::CURRENT  ;
 
392
   else if(daemonCallState == Call::DaemonStateInit::HOLD     )
 
393
      return Call::State::HOLD     ;
 
394
   else if(daemonCallState == Call::DaemonStateInit::BUSY     )
 
395
      return Call::State::BUSY     ;
 
396
   else if(daemonCallState == Call::DaemonStateInit::INACTIVE && daemonCallType == Call::CallType::INCOMING )
 
397
      return Call::State::INCOMING ;
 
398
   else if(daemonCallState == Call::DaemonStateInit::INACTIVE && daemonCallType == Call::CallType::OUTGOING )
 
399
      return Call::State::RINGING  ;
 
400
   else if(daemonCallState == Call::DaemonStateInit::INCOMING )
 
401
      return Call::State::INCOMING ;
 
402
   else if(daemonCallState == Call::DaemonStateInit::RINGING  )
 
403
      return Call::State::RINGING  ;
293
404
   else
294
 
      return CALL_STATE_FAILURE  ;
 
405
      return Call::State::FAILURE  ;
295
406
} //getStartStateFromDaemonCallState
296
407
 
 
408
 
297
409
/*****************************************************************************
298
410
 *                                                                           *
299
411
 *                                  Getters                                  *
301
413
 ****************************************************************************/
302
414
 
303
415
///Transfer state from internal to daemon internal syntaz
304
 
daemon_call_state Call::toDaemonCallState(const QString& stateName)
 
416
Call::DaemonState Call::toDaemonCallState(const QString& stateName)
305
417
{
306
 
   if(stateName == QString(CALL_STATE_CHANGE_HUNG_UP)        )
307
 
      return DAEMON_CALL_STATE_HUNG_UP ;
308
 
   if(stateName == QString(CALL_STATE_CHANGE_RINGING)        )
309
 
      return DAEMON_CALL_STATE_RINGING ;
310
 
   if(stateName == QString(CALL_STATE_CHANGE_CURRENT)        )
311
 
      return DAEMON_CALL_STATE_CURRENT ;
312
 
   if(stateName == QString(CALL_STATE_CHANGE_UNHOLD_CURRENT) )
313
 
      return DAEMON_CALL_STATE_CURRENT ;
314
 
   if(stateName == QString(CALL_STATE_CHANGE_HOLD)           )
315
 
      return DAEMON_CALL_STATE_HOLD    ;
316
 
   if(stateName == QString(CALL_STATE_CHANGE_BUSY)           )
317
 
      return DAEMON_CALL_STATE_BUSY    ;
318
 
   if(stateName == QString(CALL_STATE_CHANGE_FAILURE)        )
319
 
      return DAEMON_CALL_STATE_FAILURE ;
320
 
   
 
418
   if(stateName == Call::StateChange::HUNG_UP        )
 
419
      return Call::DaemonState::HUNG_UP ;
 
420
   if(stateName == Call::StateChange::RINGING        )
 
421
      return Call::DaemonState::RINGING ;
 
422
   if(stateName == Call::StateChange::CURRENT        )
 
423
      return Call::DaemonState::CURRENT ;
 
424
   if(stateName == Call::StateChange::UNHOLD_CURRENT )
 
425
      return Call::DaemonState::CURRENT ;
 
426
   if(stateName == Call::StateChange::HOLD           )
 
427
      return Call::DaemonState::HOLD    ;
 
428
   if(stateName == Call::StateChange::BUSY           )
 
429
      return Call::DaemonState::BUSY    ;
 
430
   if(stateName == Call::StateChange::FAILURE        )
 
431
      return Call::DaemonState::FAILURE ;
 
432
 
321
433
   qDebug() << "stateChanged signal received with unknown state.";
322
 
   return DAEMON_CALL_STATE_FAILURE    ;
 
434
   return Call::DaemonState::FAILURE    ;
323
435
} //toDaemonCallState
324
436
 
325
437
///Transform a conference call state to a proper call state
326
 
call_state Call::confStatetoCallState(const QString& stateName)
 
438
Call::State Call::confStatetoCallState(const QString& stateName)
327
439
{
328
 
   if      ( stateName == CONF_STATE_CHANGE_HOLD   )
329
 
      return CALL_STATE_CONFERENCE_HOLD;
330
 
   else if ( stateName == CONF_STATE_CHANGE_ACTIVE )
331
 
      return CALL_STATE_CONFERENCE;
 
440
   if      ( stateName == Call::ConferenceStateChange::HOLD   )
 
441
      return Call::State::CONFERENCE_HOLD;
 
442
   else if ( stateName == Call::ConferenceStateChange::ACTIVE )
 
443
      return Call::State::CONFERENCE;
332
444
   else
333
 
      return CALL_STATE_ERROR; //Well, this may bug a little
 
445
      return Call::State::ERROR; //Well, this may bug a little
334
446
}
335
447
 
336
448
///Transform a backend state into a translated string
337
 
const QString Call::toHumanStateName() const
 
449
const QString Call::toHumanStateName(const Call::State cur)
338
450
{
339
 
   switch (m_CurrentState) {
340
 
      case CALL_STATE_INCOMING:
341
 
         return ( "Ringing (in)"      );
342
 
         break;
343
 
      case CALL_STATE_RINGING:
344
 
         return ( "Ringing (out)"     );
345
 
         break;
346
 
      case CALL_STATE_CURRENT:
347
 
         return ( "Talking"           );
348
 
         break;
349
 
      case CALL_STATE_DIALING:
350
 
         return ( "Dialing"           );
351
 
         break;
352
 
      case CALL_STATE_HOLD:
353
 
         return ( "Hold"              );
354
 
         break;
355
 
      case CALL_STATE_FAILURE:
356
 
         return ( "Failed"            );
357
 
         break;
358
 
      case CALL_STATE_BUSY:
359
 
         return ( "Busy"              );
360
 
         break;
361
 
      case CALL_STATE_TRANSFERRED:
362
 
         return ( "Transfer"          );
363
 
         break;
364
 
      case CALL_STATE_TRANSF_HOLD:
365
 
         return ( "Transfer hold"     );
366
 
         break;
367
 
      case CALL_STATE_OVER:
368
 
         return ( "Over"              );
369
 
         break;
370
 
      case CALL_STATE_ERROR:
371
 
         return ( "Error"             );
372
 
         break;
373
 
      case CALL_STATE_CONFERENCE:
374
 
         return ( "Conference"        );
375
 
         break;
376
 
      case CALL_STATE_CONFERENCE_HOLD:
377
 
         return ( "Conference (hold)" );
 
451
   switch (cur) {
 
452
      case Call::State::INCOMING:
 
453
         return tr( "Ringing (in)"      );
 
454
         break;
 
455
      case Call::State::RINGING:
 
456
         return tr( "Ringing (out)"     );
 
457
         break;
 
458
      case Call::State::CURRENT:
 
459
         return tr( "Talking"           );
 
460
         break;
 
461
      case Call::State::DIALING:
 
462
         return tr( "Dialing"           );
 
463
         break;
 
464
      case Call::State::HOLD:
 
465
         return tr( "Hold"              );
 
466
         break;
 
467
      case Call::State::FAILURE:
 
468
         return tr( "Failed"            );
 
469
         break;
 
470
      case Call::State::BUSY:
 
471
         return tr( "Busy"              );
 
472
         break;
 
473
      case Call::State::TRANSFERRED:
 
474
         return tr( "Transfer"          );
 
475
         break;
 
476
      case Call::State::TRANSF_HOLD:
 
477
         return tr( "Transfer hold"     );
 
478
         break;
 
479
      case Call::State::OVER:
 
480
         return tr( "Over"              );
 
481
         break;
 
482
      case Call::State::ERROR:
 
483
         return tr( "Error"             );
 
484
         break;
 
485
      case Call::State::CONFERENCE:
 
486
         return tr( "Conference"        );
 
487
         break;
 
488
      case Call::State::CONFERENCE_HOLD:
 
489
         return tr( "Conference (hold)" );
 
490
      case Call::State::COUNT:
 
491
         return tr( "ERROR"             );
378
492
      default:
379
 
         return "";
 
493
         return QString::number(static_cast<int>(cur));
380
494
   }
381
495
}
382
496
 
 
497
QString Call::toHumanStateName() const
 
498
{
 
499
   return toHumanStateName(state());
 
500
}
 
501
 
383
502
///Get the time (second from 1 jan 1970) when the call ended
384
 
QString Call::getStopTimeStamp()     const
 
503
time_t Call::stopTimeStamp() const
385
504
{
386
 
   if (m_pStopTime == nullptr)
387
 
      return QString("0");
388
 
   return QString::number(m_pStopTime->toTime_t());
 
505
   return m_pStopTimeStamp;
389
506
}
390
507
 
391
508
///Get the time (second from 1 jan 1970) when the call started
392
 
QString Call::getStartTimeStamp()    const
 
509
time_t Call::startTimeStamp() const
393
510
{
394
 
   if (m_pStartTime == nullptr)
395
 
      return QString("0");
396
 
   return QString::number(m_pStartTime->toTime_t());
 
511
   return m_pStartTimeStamp;
397
512
}
398
513
 
399
514
///Get the number where the call have been transferred
400
 
const QString Call::getTransferNumber()    const
 
515
const QString Call::transferNumber() const
401
516
{
402
 
   return m_TransferNumber;
 
517
   return m_pTransferNumber?m_pTransferNumber->uri():QString();
403
518
}
404
519
 
405
520
///Get the call / peer number
406
 
const QString Call::getCallNumber()        const
 
521
const QString Call::dialNumber() const
407
522
{
408
 
   return m_CallNumber;
 
523
   if (m_CurrentState != Call::State::DIALING) return QString();
 
524
   if (!m_pDialNumber) {
 
525
      const_cast<Call*>(this)->m_pDialNumber = new TemporaryPhoneNumber();
 
526
   }
 
527
   return m_pDialNumber->uri();
409
528
}
410
529
 
411
530
///Return the call id
412
 
const QString Call::getCallId()            const
 
531
const QString Call::id() const
413
532
{
414
533
   return m_CallId;
415
534
}
416
535
 
417
 
///Return the peer phone number
418
 
const QString Call::getPeerPhoneNumber()   const
 
536
PhoneNumber* Call::peerPhoneNumber() const
419
537
{
420
 
   return m_PeerPhoneNumber;
 
538
   if (m_CurrentState == Call::State::DIALING) {
 
539
      if (!m_pTransferNumber) {
 
540
         const_cast<Call*>(this)->m_pTransferNumber = new TemporaryPhoneNumber(m_pPeerPhoneNumber);
 
541
      }
 
542
      if (!m_pDialNumber)
 
543
         const_cast<Call*>(this)->m_pDialNumber = new TemporaryPhoneNumber(m_pPeerPhoneNumber);
 
544
      return m_pDialNumber;
 
545
   }
 
546
   return m_pPeerPhoneNumber?m_pPeerPhoneNumber:const_cast<PhoneNumber*>(PhoneNumber::BLANK());
421
547
}
422
548
 
423
549
///Get the peer name
424
 
const QString Call::getPeerName()          const
 
550
const QString Call::peerName() const
425
551
{
426
552
   return m_PeerName;
427
553
}
428
554
 
429
555
///Generate the best possible peer name
430
 
const QString Call::getFormattedName()
 
556
const QString Call::formattedName() const
431
557
{
432
558
   if (isConference())
433
 
      return "Conference";
434
 
   else if (m_pContact && !m_pContact->getFormattedName().isEmpty())
435
 
      return m_pContact->getFormattedName();
436
 
   else if (!getPeerName().isEmpty())
 
559
      return tr("Conference");
 
560
   else if (!peerPhoneNumber())
 
561
      return "Error";
 
562
   else if (peerPhoneNumber()->contact() && !peerPhoneNumber()->contact()->formattedName().isEmpty())
 
563
      return peerPhoneNumber()->contact()->formattedName();
 
564
   else if (!peerName().isEmpty())
437
565
      return m_PeerName;
 
566
   else if (peerPhoneNumber())
 
567
      return peerPhoneNumber()->uri();
438
568
   else
439
 
      return m_PeerPhoneNumber;
 
569
      return tr("Unknown");
440
570
}
441
571
 
442
572
///If the call have a valid record
443
 
bool Call::hasRecording()                   const
444
 
{
445
 
   return !getRecordingPath().isEmpty() && QFile::exists(getRecordingPath());
 
573
bool Call::hasRecording() const
 
574
{
 
575
   return !recordingPath().isEmpty() && QFile::exists(recordingPath());
 
576
}
 
577
 
 
578
///Generate an human readable string from the difference between StartTimeStamp and StopTimeStamp (or 'now')
 
579
QString Call::length() const
 
580
{
 
581
   if (m_pStartTimeStamp == m_pStopTimeStamp) return QString(); //Invalid
 
582
   int nsec =0;
 
583
   if (m_pStopTimeStamp)
 
584
      nsec = stopTimeStamp() - startTimeStamp();//If the call is over
 
585
   else { //Time to now
 
586
      time_t curTime;
 
587
      ::time(&curTime);
 
588
      nsec = curTime - m_pStartTimeStamp;
 
589
   }
 
590
   if (nsec/3600)
 
591
      return QString("%1:%2:%3 ").arg((nsec%(3600*24))/3600).arg(((nsec%(3600*24))%3600)/60,2,10,QChar('0')).arg(((nsec%(3600*24))%3600)%60,2,10,QChar('0'));
 
592
   else
 
593
      return QString("%1:%2 ").arg(nsec/60,2,10,QChar('0')).arg(nsec%60,2,10,QChar('0'));
 
594
}
 
595
 
 
596
///Is this call part of history
 
597
bool Call::isHistory()
 
598
{
 
599
   if (m_CurrentState == Call::State::OVER && !m_History)
 
600
      m_History = true;
 
601
   return m_History;
 
602
}
 
603
 
 
604
///Is this call missed
 
605
bool Call::isMissed() const
 
606
{
 
607
   return m_Missed;
 
608
}
 
609
 
 
610
///Is the call incoming or outgoing
 
611
Call::Direction Call::direction() const
 
612
{
 
613
   return m_Direction;
446
614
}
447
615
 
448
616
///Get the current state
449
 
call_state Call::getCurrentState()          const
 
617
Call::State Call::state() const
450
618
{
451
619
   return m_CurrentState;
452
620
}
453
621
 
454
622
///Get the call recording
455
 
bool Call::getRecording()                   const
 
623
bool Call::isRecording() const
456
624
{
457
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
458
 
   ((Call*) this)->m_Recording        = callManager.getIsRecording(m_CallId);
459
625
   return m_Recording;
460
626
}
461
627
 
462
628
///Get the call account id
463
 
Account* Call::getAccount()                 const
 
629
Account* Call::account() const
464
630
{
465
 
   return AccountList::getInstance()->getAccountById(m_Account);
 
631
   return m_Account;
466
632
}
467
633
 
468
634
///Is this call a conference
469
 
bool Call::isConference()                   const
 
635
bool Call::isConference() const
470
636
{
471
637
   return m_isConference;
472
638
}
473
639
 
474
640
///Get the conference ID
475
 
const QString Call::getConfId()            const
 
641
const QString Call::confId() const
476
642
{
477
643
   return m_ConfId;
478
644
}
479
645
 
480
646
///Get the recording path
481
 
const QString Call::getRecordingPath()     const
 
647
const QString Call::recordingPath() const
482
648
{
483
649
   return m_RecordingPath;
484
650
}
485
651
 
486
652
///Get the current codec
487
 
QString Call::getCurrentCodecName()         const
 
653
QString Call::currentCodecName() const
488
654
{
489
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
655
   CallManagerInterface& callManager = DBus::CallManager::instance();
490
656
   return callManager.getCurrentAudioCodecName(m_CallId);
491
657
}
492
658
 
493
 
///Get the state
494
 
call_state Call::getState()                 const
495
 
{
496
 
   return m_CurrentState;
497
 
}
498
 
 
499
659
///Get the history state
500
 
history_state Call::getHistoryState()       const
 
660
Call::LegacyHistoryState Call::historyState() const
501
661
{
502
662
   return m_HistoryState;
503
663
}
504
664
 
505
 
///Is this call over?
506
 
bool Call::isHistory()                      const
507
 
{
508
 
   return (getState() == CALL_STATE_OVER);
509
 
}
510
 
 
511
 
///Is this call selected (useful for GUIs)
512
 
bool Call::isSelected() const
513
 
{
514
 
   return m_sSelectedCall == this;
515
 
}
516
 
 
517
665
///This function could also be called mayBeSecure or haveChancesToBeEncryptedButWeCantTell.
518
 
bool Call::isSecure() const {
 
666
bool Call::isSecure() const
 
667
{
519
668
 
520
 
   if (m_Account.isEmpty()) {
 
669
   if (!m_Account) {
521
670
      qDebug() << "Account not set, can't check security";
522
671
      return false;
523
672
   }
524
 
 
525
 
   Account* currentAccount = AccountList::getInstance()->getAccountById(m_Account);
526
 
   return currentAccount && ((currentAccount->isTlsEnable()) || (currentAccount->getTlsMethod()));
 
673
   //BUG this doesn't work
 
674
   return m_Account && ((m_Account->isTlsEnable()) || (m_Account->tlsMethod() != TlsMethodModel::Type::DEFAULT));
527
675
} //isSecure
528
676
 
529
 
Contact* Call::getContact()
530
 
{
531
 
   if (!m_pContact && m_ContactChanged) {
532
 
      m_pContact = m_pContactBackend->getContactByPhone(m_PeerPhoneNumber,true,getAccount());
533
 
   }
534
 
   return m_pContact;
535
 
}
536
 
 
537
677
///Return the renderer associated with this call or nullptr
538
 
VideoRenderer* Call::getVideoRenderer()
 
678
VideoRenderer* Call::videoRenderer() const
539
679
{
540
680
   #ifdef ENABLE_VIDEO
541
 
   return VideoModel::getInstance()->getRenderer(this);
 
681
   return VideoModel::instance()->getRenderer(this);
542
682
   #else
543
683
   return nullptr;
544
684
   #endif
554
694
///Set the transfer number
555
695
void Call::setTransferNumber(const QString& number)
556
696
{
557
 
   m_TransferNumber = number;
 
697
   if (!m_pTransferNumber) {
 
698
      m_pTransferNumber = new TemporaryPhoneNumber();
 
699
   }
 
700
   m_pTransferNumber->setUri(number);
558
701
}
559
702
 
560
703
///This call is a conference
564
707
}
565
708
 
566
709
///Set the call number
567
 
void Call::setCallNumber(const QString& number)
568
 
{
569
 
   m_CallNumber = number;
 
710
void Call::setDialNumber(const QString& number)
 
711
{
 
712
   //This is not supposed to happen, but this is not a serious issue if it does
 
713
   if (m_CurrentState != Call::State::DIALING) {
 
714
      qDebug() << "Trying to set a dial number to a non-dialing call, doing nothing";
 
715
      return;
 
716
   }
 
717
 
 
718
   if (!m_pDialNumber) {
 
719
      m_pDialNumber = new TemporaryPhoneNumber();
 
720
   }
 
721
 
 
722
   m_pDialNumber->setUri(number);
 
723
   emit dialNumberChanged(m_pDialNumber->uri());
 
724
   emit changed();
 
725
   emit changed(this);
 
726
}
 
727
 
 
728
///Set the dial number from a full phone number
 
729
void Call::setDialNumber(const PhoneNumber* number)
 
730
{
 
731
   if (m_CurrentState == Call::State::DIALING && !m_pDialNumber) {
 
732
      m_pDialNumber = new TemporaryPhoneNumber(number);
 
733
   }
 
734
   if (m_pDialNumber)
 
735
      m_pDialNumber->setUri(number->uri());
 
736
   emit dialNumberChanged(m_pDialNumber->uri());
570
737
   emit changed();
571
738
   emit changed(this);
572
739
}
573
740
 
574
741
///Set the conference ID
575
 
void Call::setConfId(QString value)
 
742
void Call::setConfId(const QString& value)
576
743
{
577
744
   m_ConfId = value;
578
745
}
581
748
void Call::setRecordingPath(const QString& path)
582
749
{
583
750
   m_RecordingPath = path;
 
751
   if (!m_RecordingPath.isEmpty()) {
 
752
      CallManagerInterface & callManager = DBus::CallManager::instance();
 
753
      connect(&callManager,SIGNAL(recordPlaybackStopped(QString)), this, SLOT(stopPlayback(QString))  );
 
754
      connect(&callManager,SIGNAL(updatePlaybackScale(QString,int,int))  , this, SLOT(updatePlayback(QString,int,int)));
 
755
   }
584
756
}
585
757
 
586
758
///Set peer name
589
761
   m_PeerName = name;
590
762
}
591
763
 
592
 
///Set selected
593
 
void Call::setSelected(const bool value)
 
764
///Set the account (DIALING only, may be ignored)
 
765
void Call::setAccount( Account* account)
594
766
{
595
 
   if (value) {
596
 
      m_sSelectedCall = this;
597
 
   }
 
767
   if (state() == Call::State::DIALING)
 
768
      m_Account = account;
598
769
}
599
770
 
600
771
/*****************************************************************************
604
775
 ****************************************************************************/
605
776
 
606
777
///The call state just changed
607
 
call_state Call::stateChanged(const QString& newStateName)
 
778
Call::State Call::stateChanged(const QString& newStateName)
608
779
{
609
 
   call_state previousState = m_CurrentState;
 
780
   Call::State previousState = m_CurrentState;
610
781
   if (!m_isConference) {
611
 
      daemon_call_state dcs = toDaemonCallState(newStateName);
612
 
      changeCurrentState(stateChangedStateMap[m_CurrentState][dcs]);
613
 
 
614
 
      CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
782
      Call::DaemonState dcs = toDaemonCallState(newStateName);
 
783
      if (dcs == Call::DaemonState::COUNT || m_CurrentState == Call::State::COUNT) {
 
784
         qDebug() << "Error: Invalid state change";
 
785
         return Call::State::FAILURE;
 
786
      }
 
787
 
 
788
      try {
 
789
         changeCurrentState(stateChangedStateMap[m_CurrentState][dcs]);
 
790
      }
 
791
      catch(Call::State& state) {
 
792
         qDebug() << "State change failed (stateChangedStateMap)" << state;
 
793
         m_CurrentState = Call::State::ERROR;
 
794
         emit stateChanged();
 
795
         emit changed();
 
796
         return m_CurrentState;
 
797
      }
 
798
      catch(Call::DaemonState& state) {
 
799
         qDebug() << "State change failed (stateChangedStateMap)" << state;
 
800
         m_CurrentState = Call::State::ERROR;
 
801
         emit stateChanged();
 
802
         emit changed();
 
803
         return m_CurrentState;
 
804
      }
 
805
      catch (...) {
 
806
         qDebug() << "State change failed (stateChangedStateMap) other";;
 
807
         m_CurrentState = Call::State::ERROR;
 
808
         emit stateChanged();
 
809
         emit changed();
 
810
         return m_CurrentState;
 
811
      }
 
812
 
 
813
      CallManagerInterface & callManager = DBus::CallManager::instance();
615
814
      MapStringString details = callManager.getCallDetails(m_CallId).value();
616
 
      if (details[CALL_PEER_NAME] != m_PeerName)
617
 
         m_PeerName = details[CALL_PEER_NAME];
 
815
      if (details[Call::DetailsMapFields::PEER_NAME] != m_PeerName)
 
816
         m_PeerName = details[Call::DetailsMapFields::PEER_NAME];
618
817
 
619
 
      (this->*(stateChangedFunctionMap[previousState][dcs]))();
 
818
      try {
 
819
         (this->*(stateChangedFunctionMap[previousState][dcs]))();
 
820
      }
 
821
      catch(Call::State& state) {
 
822
         qDebug() << "State change failed (stateChangedFunctionMap)" << state;
 
823
         m_CurrentState = Call::State::ERROR;
 
824
         emit stateChanged();
 
825
         emit changed();
 
826
         return m_CurrentState;
 
827
      }
 
828
      catch(Call::DaemonState& state) {
 
829
         qDebug() << "State change failed (stateChangedFunctionMap)" << state;
 
830
         m_CurrentState = Call::State::ERROR;
 
831
         emit stateChanged();
 
832
         emit changed();
 
833
         return m_CurrentState;
 
834
      }
 
835
      catch (...) {
 
836
         qDebug() << "State change failed (stateChangedFunctionMap) other";;
 
837
         m_CurrentState = Call::State::ERROR;
 
838
         emit stateChanged();
 
839
         emit changed();
 
840
         return m_CurrentState;
 
841
      }
620
842
   }
621
843
   else {
622
844
      //Until now, it does not worth using stateChangedStateMap, conferences are quite simple
623
845
      m_CurrentState = confStatetoCallState(newStateName);
624
 
   }
 
846
      emit stateChanged();
 
847
   }
 
848
   if ((m_CurrentState == Call::State::HOLD || m_CurrentState == Call::State::CURRENT) && !m_pTimer) {
 
849
      m_pTimer = new QTimer(this);
 
850
      m_pTimer->setInterval(1000);
 
851
      connect(m_pTimer,SIGNAL(timeout()),this,SLOT(updated()));
 
852
      m_pTimer->start();
 
853
   }
 
854
   if (m_CurrentState != Call::State::DIALING && m_pDialNumber) {
 
855
      if (!m_pPeerPhoneNumber)
 
856
         m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber);
 
857
      delete m_pDialNumber;
 
858
      m_pDialNumber = nullptr;
 
859
   }
 
860
   emit changed();
 
861
   emit changed(this);
625
862
   qDebug() << "Calling stateChanged " << newStateName << " -> " << toDaemonCallState(newStateName) << " on call with state " << previousState << ". Become " << m_CurrentState;
626
863
   return m_CurrentState;
627
864
} //stateChanged
628
865
 
629
866
///An account have been performed
630
 
call_state Call::actionPerformed(call_action action)
 
867
Call::State Call::performAction(Call::Action action)
631
868
{
632
 
   call_state previousState = m_CurrentState;
 
869
   const Call::State previousState = m_CurrentState;
633
870
   //update the state
634
 
   if (previousState < 13 && action < 5) {
 
871
   try {
635
872
      changeCurrentState(actionPerformedStateMap[previousState][action]);
636
 
      //execute the action associated with this transition
 
873
   }
 
874
   catch(Call::State& state) {
 
875
      qDebug() << "State change failed (actionPerformedStateMap)" << state;
 
876
      m_CurrentState = Call::State::ERROR;
 
877
      emit stateChanged();
 
878
      emit changed();
 
879
      return Call::State::ERROR;
 
880
   }
 
881
   catch (...) {
 
882
      qDebug() << "State change failed (actionPerformedStateMap) other";;
 
883
      m_CurrentState = Call::State::ERROR;
 
884
      emit stateChanged();
 
885
      emit changed();
 
886
      return m_CurrentState;
 
887
   }
 
888
 
 
889
   //execute the action associated with this transition
 
890
   try {
637
891
      (this->*(actionPerformedFunctionMap[previousState][action]))();
638
 
      qDebug() << "Calling action " << action << " on call with state " << previousState << ". Become " << m_CurrentState;
639
 
      //return the new state
640
 
   }
 
892
   }
 
893
   catch(Call::State& state) {
 
894
      qDebug() << "State change failed (actionPerformedFunctionMap)" << state;
 
895
      m_CurrentState = Call::State::ERROR;
 
896
      emit stateChanged();
 
897
      emit changed();
 
898
      return Call::State::ERROR;
 
899
   }
 
900
   catch(Call::Action& action) {
 
901
      qDebug() << "State change failed (actionPerformedFunctionMap)" << action;
 
902
      m_CurrentState = Call::State::ERROR;
 
903
      emit stateChanged();
 
904
      emit changed();
 
905
      return Call::State::ERROR;
 
906
   }
 
907
   catch (...) {
 
908
      qDebug() << "State change failed (actionPerformedFunctionMap) other";;
 
909
      m_CurrentState = Call::State::ERROR;
 
910
      emit stateChanged();
 
911
      emit changed();
 
912
      return m_CurrentState;
 
913
   }
 
914
   qDebug() << "Calling action " << action << " on call with state " << previousState << ". Become " << m_CurrentState;
641
915
   return m_CurrentState;
642
916
} //actionPerformed
643
917
 
644
918
///Change the state
645
 
void Call::changeCurrentState(call_state newState)
 
919
void Call::changeCurrentState(Call::State newState)
646
920
{
 
921
   if (newState == Call::State::COUNT) {
 
922
      qDebug() << "Error: Call reach invalid state";
 
923
      m_CurrentState = Call::State::ERROR;
 
924
      throw newState;
 
925
   }
 
926
 
647
927
   m_CurrentState = newState;
648
928
 
 
929
   emit stateChanged();
649
930
   emit changed();
650
931
   emit changed(this);
651
932
 
652
 
   if (m_CurrentState == CALL_STATE_OVER)
 
933
   if (m_CurrentState == Call::State::OVER)
653
934
      emit isOver(this);
654
935
}
655
936
 
 
937
///Set the start timestamp and update the cache
 
938
void Call::setStartTimeStamp(time_t stamp)
 
939
{
 
940
   m_pStartTimeStamp = stamp;
 
941
   //While the HistoryConst is not directly related to the call concept,
 
942
   //It is called to often to ignore
 
943
   m_HistoryConst = HistoryTimeCategoryModel::timeToHistoryConst(m_pStartTimeStamp);
 
944
}
 
945
 
656
946
///Send a text message
657
947
void Call::sendTextMessage(QString message)
658
948
{
659
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
949
   CallManagerInterface& callManager = DBus::CallManager::instance();
660
950
   Q_NOREPLY callManager.sendTextMessage(isConference()?m_ConfId:m_CallId,message);
661
 
   qDebug() << "MODEL IS" << m_pImModel;
662
951
   if (!m_pImModel) {
663
 
        m_pImModel = InstantMessagingModelManager::getInstance()->getModel(this);
 
952
      m_pImModel = InstantMessagingModelManager::instance()->getModel(this);
664
953
   }
665
 
   qDebug() << "MODEL IS2" << m_pImModel;
666
954
   m_pImModel->addOutgoingMessage(message);
667
955
}
668
956
 
669
 
///Private version of setStartTime
670
 
QDateTime* Call::setStartTime_private(QDateTime* time)
671
 
{
672
 
   //if (m_pStartTime && time)
673
 
   //   delete m_pStartTime;
674
 
   
675
 
   return m_pStartTime = time;
676
 
}
677
 
 
678
 
///Private version of setStopTime
679
 
QDateTime* Call::setStopTime_private(QDateTime* time)
680
 
{
681
 
   //if (m_pStopTime && time)
682
 
   //   delete m_pStopTime;
683
 
   return m_pStopTime  = time;
684
 
}
685
957
 
686
958
/*****************************************************************************
687
959
 *                                                                           *
693
965
///Do nothing (literally)
694
966
void Call::nothing()
695
967
{
696
 
   
 
968
   //nop
 
969
}
 
970
 
 
971
void Call::error()
 
972
{
 
973
   if (videoRenderer()) {
 
974
      //Well, in this case we have no choice, it still doesn't belong here
 
975
      videoRenderer()->stopRendering();
 
976
   }
 
977
   throw QString("There was an error handling your call, please restart SFLPhone.Is you encounter this problem often, \
 
978
   please open SFLPhone-KDE in a terminal and send this last 100 lines before this message in a bug report at \
 
979
   https://projects.savoirfairelinux.com/projects/sflphone/issues");
697
980
}
698
981
 
699
982
///Accept the call
700
983
void Call::accept()
701
984
{
702
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
985
   CallManagerInterface & callManager = DBus::CallManager::instance();
703
986
   qDebug() << "Accepting call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
704
987
   Q_NOREPLY callManager.accept(m_CallId);
705
 
   setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
706
 
   this->m_HistoryState = INCOMING;
 
988
   time_t curTime;
 
989
   ::time(&curTime);
 
990
   setStartTimeStamp(curTime);
 
991
   this->m_HistoryState = LegacyHistoryState::INCOMING;
 
992
   m_Direction = Call::Direction::INCOMING;
 
993
   if (!m_pTimer) {
 
994
      m_pTimer = new QTimer(this);
 
995
      m_pTimer->setInterval(1000);
 
996
      connect(m_pTimer,SIGNAL(timeout()),this,SLOT(updated()));
 
997
      m_pTimer->start();
 
998
   }
707
999
}
708
1000
 
709
1001
///Refuse the call
710
1002
void Call::refuse()
711
1003
{
712
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1004
   CallManagerInterface & callManager = DBus::CallManager::instance();
713
1005
   qDebug() << "Refusing call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
714
1006
   Q_NOREPLY callManager.refuse(m_CallId);
715
 
   setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
716
 
   this->m_HistoryState = MISSED;
 
1007
   time_t curTime;
 
1008
   ::time(&curTime);
 
1009
   setStartTimeStamp(curTime);
 
1010
   this->m_HistoryState = Call::LegacyHistoryState::MISSED;
 
1011
   m_Missed = true;
717
1012
}
718
1013
 
719
1014
///Accept the transfer
720
1015
void Call::acceptTransf()
721
1016
{
722
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
723
 
   qDebug() << "Accepting call and transferring it to number : " << m_TransferNumber << ". callId : " << m_CallId  << "ConfId:" << m_ConfId;
 
1017
   if (!m_pTransferNumber) {
 
1018
      qDebug() << "Trying to transfer to no one";
 
1019
      return;
 
1020
   }
 
1021
   CallManagerInterface & callManager = DBus::CallManager::instance();
 
1022
   qDebug() << "Accepting call and transferring it to number : " << m_pTransferNumber->uri() << ". callId : " << m_CallId  << "ConfId:" << m_ConfId;
724
1023
   callManager.accept(m_CallId);
725
 
   Q_NOREPLY callManager.transfer(m_CallId, m_TransferNumber);
 
1024
   Q_NOREPLY callManager.transfer(m_CallId, m_pTransferNumber->uri());
726
1025
}
727
1026
 
728
1027
///Put the call on hold
729
1028
void Call::acceptHold()
730
1029
{
731
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1030
   CallManagerInterface & callManager = DBus::CallManager::instance();
732
1031
   qDebug() << "Accepting call and holding it. callId : " << m_CallId  << "ConfId:" << m_ConfId;
733
1032
   callManager.accept(m_CallId);
734
1033
   Q_NOREPLY callManager.hold(m_CallId);
735
 
   this->m_HistoryState = INCOMING;
 
1034
   this->m_HistoryState = LegacyHistoryState::INCOMING;
 
1035
   m_Direction = Call::Direction::INCOMING;
736
1036
}
737
1037
 
738
1038
///Hang up
739
1039
void Call::hangUp()
740
1040
{
741
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
742
 
   setStopTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1041
   CallManagerInterface & callManager = DBus::CallManager::instance();
 
1042
   time_t curTime;
 
1043
   ::time(&curTime);
 
1044
   m_pStopTimeStamp = curTime;
743
1045
   qDebug() << "Hanging up call. callId : " << m_CallId << "ConfId:" << m_ConfId;
 
1046
   bool ret;
 
1047
   if (videoRenderer()) { //TODO remove, cheap hack
 
1048
      videoRenderer()->stopRendering();
 
1049
   }
744
1050
   if (!isConference())
745
 
      Q_NOREPLY callManager.hangUp(m_CallId);
 
1051
      ret = callManager.hangUp(m_CallId);
746
1052
   else
747
 
      Q_NOREPLY callManager.hangUpConference(m_ConfId);
 
1053
      ret = callManager.hangUpConference(m_ConfId);
 
1054
   if (!ret) { //Can happen if the daemon crash and open again
 
1055
      qDebug() << "Error: Invalid call, the daemon may have crashed";
 
1056
      m_CurrentState = Call::State::OVER;
 
1057
      emit stateChanged();
 
1058
      emit changed();
 
1059
      emit changed(this);
 
1060
   }
 
1061
   if (m_pTimer)
 
1062
      m_pTimer->stop();
 
1063
}
 
1064
 
 
1065
///Remove the call without contacting the daemon
 
1066
void Call::remove()
 
1067
{
 
1068
   m_CurrentState = Call::State::OVER;
 
1069
   emit stateChanged();
 
1070
   emit changed();
 
1071
   emit changed(this);
748
1072
}
749
1073
 
750
1074
///Cancel this call
751
1075
void Call::cancel()
752
1076
{
753
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1077
   CallManagerInterface & callManager = DBus::CallManager::instance();
754
1078
   qDebug() << "Canceling call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
 
1079
   emit dialNumberChanged(QString());
755
1080
   Q_NOREPLY callManager.hangUp(m_CallId);
756
1081
}
757
1082
 
758
1083
///Put on hold
759
1084
void Call::hold()
760
1085
{
761
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1086
   CallManagerInterface & callManager = DBus::CallManager::instance();
762
1087
   qDebug() << "Holding call. callId : " << m_CallId << "ConfId:" << m_ConfId;
763
1088
   if (!isConference())
764
1089
      Q_NOREPLY callManager.hold(m_CallId);
769
1094
///Start the call
770
1095
void Call::call()
771
1096
{
772
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1097
   CallManagerInterface& callManager = DBus::CallManager::instance();
773
1098
   qDebug() << "account = " << m_Account;
774
 
   if(m_Account.isEmpty()) {
 
1099
   if(!m_Account) {
775
1100
      qDebug() << "Account is not set, taking the first registered.";
776
 
      this->m_Account = AccountList::getCurrentAccount()->getAccountId();
777
 
   }
778
 
   if(!m_Account.isEmpty()) {
779
 
      qDebug() << "Calling " << m_CallNumber << " with account " << m_Account << ". callId : " << m_CallId  << "ConfId:" << m_ConfId;
780
 
      callManager.placeCall(m_Account, m_CallId, m_CallNumber);
781
 
      this->m_Account = m_Account;
782
 
      this->m_PeerPhoneNumber = m_CallNumber;
783
 
      m_ContactChanged = true;
 
1101
      this->m_Account = AccountListModel::currentAccount();
 
1102
   }
 
1103
   //Calls to empty URI should not be allowed, sflphoned will go crazy
 
1104
   if (m_pDialNumber->uri().isEmpty()) {
 
1105
      qDebug() << "Trying to call an empty URI";
 
1106
      m_CurrentState = Call::State::FAILURE;
 
1107
      if (m_pDialNumber)
 
1108
         emit dialNumberChanged(QString());
 
1109
      setPeerName(tr("Failure"));
 
1110
      emit stateChanged();
 
1111
      emit changed();
 
1112
      delete m_pDialNumber;
 
1113
      m_pDialNumber = nullptr;
 
1114
   }
 
1115
   //Normal case
 
1116
   else if(m_Account) {
 
1117
      qDebug() << "Calling " << peerPhoneNumber()->uri() << " with account " << m_Account << ". callId : " << m_CallId  << "ConfId:" << m_ConfId;
 
1118
      callManager.placeCall(m_Account->id(), m_CallId, m_pDialNumber->uri());
 
1119
      this->m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->getNumber(m_pDialNumber->uri(),account());
784
1120
      if (m_pContactBackend) {
785
 
         if (getContact())
786
 
            m_PeerName = m_pContact->getFormattedName();
787
 
      }
788
 
      setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
789
 
      this->m_HistoryState = OUTGOING;
 
1121
         if (peerPhoneNumber()->contact())
 
1122
            m_PeerName = peerPhoneNumber()->contact()->formattedName();
 
1123
      }
 
1124
      connect(peerPhoneNumber(),SIGNAL(presentChanged(bool)),this,SLOT(updated()));
 
1125
      time_t curTime;
 
1126
      ::time(&curTime);
 
1127
      setStartTimeStamp(curTime);
 
1128
      this->m_HistoryState = LegacyHistoryState::OUTGOING;
 
1129
      m_Direction = Call::Direction::OUTGOING;
 
1130
      if (peerPhoneNumber()) {
 
1131
         peerPhoneNumber()->addCall(this);
 
1132
      }
 
1133
      if (m_pDialNumber)
 
1134
         emit dialNumberChanged(QString());
 
1135
      delete m_pDialNumber;
 
1136
      m_pDialNumber = nullptr;
790
1137
   }
791
1138
   else {
792
 
      qDebug() << "Trying to call " << m_TransferNumber << " with no account registered . callId : " << m_CallId  << "ConfId:" << m_ConfId;
793
 
      this->m_HistoryState = NONE;
794
 
      throw "No account registered!";
 
1139
      qDebug() << "Trying to call " << (m_pTransferNumber?m_pTransferNumber->uri():"ERROR") 
 
1140
         << " with no account registered . callId : " << m_CallId  << "ConfId:" << m_ConfId;
 
1141
      this->m_HistoryState = LegacyHistoryState::NONE;
 
1142
      throw tr("No account registered!");
795
1143
   }
796
1144
}
797
1145
 
798
1146
///Trnasfer the call
799
1147
void Call::transfer()
800
1148
{
801
 
   if (!m_TransferNumber.isEmpty()) {
802
 
      CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
803
 
      qDebug() << "Transferring call to number : " << m_TransferNumber << ". callId : " << m_CallId;
804
 
      Q_NOREPLY callManager.transfer(m_CallId, m_TransferNumber);
805
 
      setStopTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1149
   if (m_pTransferNumber) {
 
1150
      CallManagerInterface & callManager = DBus::CallManager::instance();
 
1151
      qDebug() << "Transferring call to number : " << m_pTransferNumber->uri() << ". callId : " << m_CallId;
 
1152
      Q_NOREPLY callManager.transfer(m_CallId, m_pTransferNumber->uri());
 
1153
      time_t curTime;
 
1154
      ::time(&curTime);
 
1155
      m_pStopTimeStamp = curTime;
806
1156
   }
807
1157
}
808
1158
 
809
1159
///Unhold the call
810
1160
void Call::unhold()
811
1161
{
812
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1162
   CallManagerInterface & callManager = DBus::CallManager::instance();
813
1163
   qDebug() << "Unholding call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
814
1164
   if (!isConference())
815
1165
      Q_NOREPLY callManager.unhold(m_CallId);
820
1170
///Record the call
821
1171
void Call::setRecord()
822
1172
{
823
 
   CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
 
1173
   CallManagerInterface & callManager = DBus::CallManager::instance();
824
1174
   qDebug() << "Setting record " << !m_Recording << " for call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
825
 
   Q_NOREPLY callManager.setRecording((!m_isConference)?m_CallId:m_ConfId);
826
 
   bool oldRecStatus = m_Recording;
827
 
   m_Recording = !m_Recording;
828
 
   if (oldRecStatus != m_Recording) {
829
 
      emit changed();
830
 
      emit changed(this);
831
 
   }
 
1175
   callManager.toggleRecording((!m_isConference)?m_CallId:m_ConfId);
832
1176
}
833
1177
 
834
1178
///Start the timer
835
1179
void Call::start()
836
1180
{
837
1181
   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
838
 
   setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1182
   time_t curTime;
 
1183
   ::time(&curTime);
 
1184
   emit changed();
 
1185
   emit changed(this);
 
1186
   if (m_pDialNumber) {
 
1187
      if (!m_pPeerPhoneNumber)
 
1188
         m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber);
 
1189
      delete m_pDialNumber;
 
1190
      m_pDialNumber = nullptr;
 
1191
   }
 
1192
   setStartTimeStamp(curTime);
839
1193
}
840
1194
 
841
1195
///Toggle the timer
842
1196
void Call::startStop()
843
1197
{
844
1198
   qDebug() << "Starting and stoping call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
845
 
   setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
846
 
   setStopTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1199
   time_t curTime;
 
1200
   ::time(&curTime);
 
1201
   setStartTimeStamp(curTime);
 
1202
   m_pStopTimeStamp  = curTime;
847
1203
}
848
1204
 
849
1205
///Stop the timer
850
1206
void Call::stop()
851
1207
{
852
1208
   qDebug() << "Stoping call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
853
 
   setStopTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1209
   if (videoRenderer()) { //TODO remove, cheap hack
 
1210
      videoRenderer()->stopRendering();
 
1211
   }
 
1212
   time_t curTime;
 
1213
   ::time(&curTime);
 
1214
   m_pStopTimeStamp = curTime;
854
1215
}
855
1216
 
856
1217
///Handle error instead of crashing
857
1218
void Call::startWeird()
858
1219
{
859
1220
   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << m_ConfId;
860
 
   setStartTime_private(new QDateTime(QDateTime::currentDateTime()));
 
1221
   time_t curTime;
 
1222
   ::time(&curTime);
 
1223
   setStartTimeStamp(curTime);
861
1224
   qDebug() << "Warning : call " << m_CallId << " had an unexpected transition of state at its start.";
862
1225
}
863
1226
 
864
1227
///Print a warning
865
1228
void Call::warning()
866
1229
{
867
 
   qDebug() << "Warning : call " << m_CallId << " had an unexpected transition of state.";
 
1230
   qWarning() << "Warning : call " << m_CallId << " had an unexpected transition of state.(" << m_CurrentState << ")";
 
1231
   switch (m_CurrentState) {
 
1232
      case Call::State::FAILURE        :
 
1233
      case Call::State::ERROR          :
 
1234
      case Call::State::COUNT          :
 
1235
         //If not stopped, then the counter will keep going
 
1236
         //Getting here indicate something wrong happened
 
1237
         //It can be normal, aka, an invalid URI such as '><'
 
1238
         // or an SFLPhone-KDE bug
 
1239
         stop();
 
1240
         break;
 
1241
      case Call::State::TRANSFERRED    :
 
1242
      case Call::State::TRANSF_HOLD    :
 
1243
      case Call::State::DIALING        :
 
1244
      case Call::State::INCOMING       :
 
1245
      case Call::State::RINGING        :
 
1246
      case Call::State::CURRENT        :
 
1247
      case Call::State::HOLD           :
 
1248
      case Call::State::BUSY           :
 
1249
      case Call::State::OVER           :
 
1250
      case Call::State::CONFERENCE     :
 
1251
      case Call::State::CONFERENCE_HOLD:
 
1252
      default:
 
1253
         break;
 
1254
   }
868
1255
}
869
1256
 
870
1257
/*****************************************************************************
876
1263
///Input text on the call item
877
1264
void Call::appendText(const QString& str)
878
1265
{
879
 
   QString* editNumber;
880
 
   
 
1266
   TemporaryPhoneNumber* editNumber = nullptr;
 
1267
 
881
1268
   switch (m_CurrentState) {
882
 
   case CALL_STATE_TRANSFERRED :
883
 
   case CALL_STATE_TRANSF_HOLD :
884
 
      editNumber = &m_TransferNumber;
885
 
      break;
886
 
   case CALL_STATE_DIALING     :
887
 
      editNumber = &m_CallNumber;
888
 
      break;
889
 
   default                     :
 
1269
   case Call::State::TRANSFERRED :
 
1270
   case Call::State::TRANSF_HOLD :
 
1271
      editNumber = m_pTransferNumber;
 
1272
      break;
 
1273
   case Call::State::DIALING     :
 
1274
      editNumber = m_pDialNumber;
 
1275
      break;
 
1276
   case Call::State::INCOMING:
 
1277
   case Call::State::RINGING:
 
1278
   case Call::State::CURRENT:
 
1279
   case Call::State::HOLD:
 
1280
   case Call::State::FAILURE:
 
1281
   case Call::State::BUSY:
 
1282
   case Call::State::OVER:
 
1283
   case Call::State::ERROR:
 
1284
   case Call::State::CONFERENCE:
 
1285
   case Call::State::CONFERENCE_HOLD:
 
1286
   case Call::State::COUNT:
 
1287
   default:
890
1288
      qDebug() << "Backspace on call not editable. Doing nothing.";
891
1289
      return;
892
1290
   }
893
1291
 
894
 
   editNumber->append(str);
 
1292
   if (editNumber) {
 
1293
      editNumber->setUri(editNumber->uri()+str);
 
1294
      if (state() == Call::State::DIALING)
 
1295
         emit dialNumberChanged(editNumber->uri());
 
1296
   }
 
1297
   else
 
1298
      qDebug() << "TemporaryPhoneNumber not defined";
 
1299
 
895
1300
 
896
1301
   emit changed();
897
1302
   emit changed(this);
900
1305
///Remove the last character
901
1306
void Call::backspaceItemText()
902
1307
{
903
 
   QString* editNumber;
 
1308
   TemporaryPhoneNumber* editNumber = nullptr;
904
1309
 
905
1310
   switch (m_CurrentState) {
906
 
      case CALL_STATE_TRANSFERRED      :
907
 
      case CALL_STATE_TRANSF_HOLD      :
908
 
         editNumber = &m_TransferNumber;
909
 
         break;
910
 
      case CALL_STATE_DIALING          :
911
 
         editNumber = &m_CallNumber;
912
 
         break;
 
1311
      case Call::State::TRANSFERRED      :
 
1312
      case Call::State::TRANSF_HOLD      :
 
1313
         editNumber = m_pTransferNumber;
 
1314
         break;
 
1315
      case Call::State::DIALING          :
 
1316
         editNumber = m_pDialNumber;
 
1317
         break;
 
1318
      case Call::State::INCOMING:
 
1319
      case Call::State::RINGING:
 
1320
      case Call::State::CURRENT:
 
1321
      case Call::State::HOLD:
 
1322
      case Call::State::FAILURE:
 
1323
      case Call::State::BUSY:
 
1324
      case Call::State::OVER:
 
1325
      case Call::State::ERROR:
 
1326
      case Call::State::CONFERENCE:
 
1327
      case Call::State::CONFERENCE_HOLD:
 
1328
      case Call::State::COUNT:
913
1329
      default                          :
914
1330
         qDebug() << "Backspace on call not editable. Doing nothing.";
915
1331
         return;
916
1332
   }
917
 
   QString text = *editNumber;
918
 
   int textSize = text.size();
919
 
   if(textSize > 0) {
920
 
      *editNumber = text.remove(textSize-1, 1);
921
 
      emit changed();
922
 
      emit changed(this);
923
 
   }
924
 
   else {
925
 
      changeCurrentState(CALL_STATE_OVER);
926
 
   }
927
 
}
928
 
 
 
1333
   if (editNumber) {
 
1334
      QString text = editNumber->uri();
 
1335
      const int textSize = text.size();
 
1336
      if(textSize > 0) {
 
1337
         editNumber->setUri(text.remove(textSize-1, 1));
 
1338
         emit changed();
 
1339
         emit changed(this);
 
1340
      }
 
1341
      else {
 
1342
         changeCurrentState(Call::State::OVER);
 
1343
      }
 
1344
   }
 
1345
   else
 
1346
      qDebug() << "TemporaryPhoneNumber not defined";
 
1347
}
 
1348
 
 
1349
///Reset the string a dialing or transfer call
 
1350
void Call::reset()
 
1351
{
 
1352
   TemporaryPhoneNumber* editNumber = nullptr;
 
1353
 
 
1354
   switch (m_CurrentState) {
 
1355
      case Call::State::TRANSFERRED      :
 
1356
      case Call::State::TRANSF_HOLD      :
 
1357
         editNumber = m_pTransferNumber;
 
1358
         break;
 
1359
      case Call::State::DIALING          :
 
1360
         editNumber = m_pDialNumber;
 
1361
         break;
 
1362
      case Call::State::INCOMING         :
 
1363
      case Call::State::RINGING          :
 
1364
      case Call::State::CURRENT          :
 
1365
      case Call::State::HOLD             :
 
1366
      case Call::State::FAILURE          :
 
1367
      case Call::State::BUSY             :
 
1368
      case Call::State::OVER             :
 
1369
      case Call::State::ERROR            :
 
1370
      case Call::State::CONFERENCE       :
 
1371
      case Call::State::CONFERENCE_HOLD  :
 
1372
      case Call::State::COUNT:
 
1373
      default                            :
 
1374
         qDebug() << "Cannot reset" << m_CurrentState << "calls";
 
1375
         return;
 
1376
   }
 
1377
   if (editNumber) {
 
1378
      editNumber->setUri(QString());
 
1379
   }
 
1380
}
929
1381
 
930
1382
/*****************************************************************************
931
1383
 *                                                                           *
933
1385
 *                                                                           *
934
1386
 ****************************************************************************/
935
1387
 
 
1388
void Call::updated()
 
1389
{
 
1390
   emit changed();
 
1391
   emit changed(this);
 
1392
}
 
1393
 
936
1394
///Play the record, if any
937
1395
void Call::playRecording()
938
1396
{
939
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
940
 
   bool retval = callManager.startRecordedFilePlayback(getRecordingPath());
 
1397
   CallManagerInterface& callManager = DBus::CallManager::instance();
 
1398
   const bool retval = callManager.startRecordedFilePlayback(recordingPath());
941
1399
   if (retval)
942
1400
      emit playbackStarted();
943
1401
}
945
1403
///Stop the record, if any
946
1404
void Call::stopRecording()
947
1405
{
948
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
949
 
   Q_NOREPLY callManager.stopRecordedFilePlayback(getRecordingPath());
 
1406
   CallManagerInterface& callManager = DBus::CallManager::instance();
 
1407
   Q_NOREPLY callManager.stopRecordedFilePlayback(recordingPath());
950
1408
   emit playbackStopped(); //TODO remove this, it is a workaround for bug #11942
951
1409
}
952
1410
 
953
1411
///seek the record, if any
954
1412
void Call::seekRecording(double position)
955
1413
{
956
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
 
1414
   CallManagerInterface& callManager = DBus::CallManager::instance();
957
1415
   Q_NOREPLY callManager.recordPlaybackSeek(position);
958
1416
}
959
1417
 
960
1418
///Daemon record playback stopped
961
 
void Call::stopPlayback(QString filePath)
 
1419
void Call::stopPlayback(const QString& filePath)
962
1420
{
963
 
   if (filePath == getRecordingPath()) {
 
1421
   if (filePath == recordingPath()) {
964
1422
      emit playbackStopped();
965
1423
   }
966
1424
}
967
1425
 
968
1426
///Daemon playback position chnaged
969
 
void Call::updatePlayback(int position,int size)
970
 
{
971
 
   emit playbackPositionChanged(position,size);
972
 
}
973
 
 
974
 
///Called to notice the call thatits contact might be outdated
975
 
void Call::contactBackendChanged()
976
 
{
977
 
   m_ContactChanged = true;
 
1427
void Call::updatePlayback(const QString& path, int position,int size)
 
1428
{
 
1429
   if (path == m_RecordingPath) {
 
1430
      emit playbackPositionChanged(position,size);
 
1431
   }
 
1432
}
 
1433
 
 
1434
UserActionModel* Call::userActionModel() const
 
1435
{
 
1436
   return m_pUserActionModel;
 
1437
}
 
1438
 
 
1439
///Common source for model data roles
 
1440
QVariant Call::roleData(int role) const
 
1441
{
 
1442
   const Contact* ct = peerPhoneNumber()?peerPhoneNumber()->contact():nullptr;
 
1443
   switch (role) {
 
1444
      case Call::Role::Name:
 
1445
      case Qt::DisplayRole:
 
1446
         if (isConference())
 
1447
            return tr("Conference");
 
1448
         else if (state() == Call::State::DIALING)
 
1449
            return dialNumber();
 
1450
         else if (m_PeerName.isEmpty())
 
1451
            return ct?ct->formattedName():peerPhoneNumber()?peerPhoneNumber()->uri():dialNumber();
 
1452
         else
 
1453
            return formattedName();
 
1454
         break;
 
1455
      case Qt::EditRole:
 
1456
         return dialNumber();
 
1457
      case Call::Role::Number:
 
1458
         return peerPhoneNumber()->uri();
 
1459
         break;
 
1460
      case Call::Role::Direction2:
 
1461
         return static_cast<int>(m_Direction);
 
1462
         break;
 
1463
      case Call::Role::Date:
 
1464
         return (int)startTimeStamp();
 
1465
         break;
 
1466
      case Call::Role::Length:
 
1467
         return length();
 
1468
         break;
 
1469
      case Call::Role::FormattedDate:
 
1470
         return QDateTime::fromTime_t(startTimeStamp()).toString();
 
1471
         break;
 
1472
      case Call::Role::HasRecording:
 
1473
         return hasRecording();
 
1474
         break;
 
1475
      case Call::Role::Historystate:
 
1476
         return static_cast<int>(historyState());
 
1477
         break;
 
1478
      case Call::Role::Filter: {
 
1479
         QString normStripppedC;
 
1480
         foreach(QChar char2,QString(static_cast<int>(historyState())+'\n'+roleData(Call::Role::Name).toString()+'\n'+
 
1481
            roleData(Call::Role::Number).toString()).toLower().normalized(QString::NormalizationForm_KD) ) {
 
1482
            if (!char2.combiningClass())
 
1483
               normStripppedC += char2;
 
1484
         }
 
1485
         return normStripppedC;
 
1486
         }
 
1487
         break;
 
1488
      case Call::Role::FuzzyDate:
 
1489
         return (int)m_HistoryConst;
 
1490
         break;
 
1491
      case Call::Role::IsBookmark:
 
1492
         return false;
 
1493
         break;
 
1494
      case Call::Role::Security:
 
1495
         return isSecure();
 
1496
         break;
 
1497
      case Call::Role::Department:
 
1498
         return ct?ct->department():QVariant();
 
1499
         break;
 
1500
      case Call::Role::Email:
 
1501
         return ct?ct->preferredEmail():QVariant();
 
1502
         break;
 
1503
      case Call::Role::Organisation:
 
1504
         return ct?ct->organization():QVariant();
 
1505
         break;
 
1506
      case Call::Role::Codec:
 
1507
         return currentCodecName();
 
1508
         break;
 
1509
      case Call::Role::IsConference:
 
1510
         return isConference();
 
1511
         break;
 
1512
      case Call::Role::Object:
 
1513
         return QVariant::fromValue(const_cast<Call*>(this));
 
1514
         break;
 
1515
      case Call::Role::PhoneNu:
 
1516
         return QVariant::fromValue(const_cast<PhoneNumber*>(peerPhoneNumber()));
 
1517
         break;
 
1518
      case Call::Role::PhotoPtr:
 
1519
         return QVariant::fromValue((void*)(ct?ct->photo():nullptr));
 
1520
         break;
 
1521
      case Call::Role::CallState:
 
1522
         return static_cast<int>(state());
 
1523
         break;
 
1524
      case Call::Role::Id:
 
1525
         return ((m_isConference)?confId():id());
 
1526
         break;
 
1527
      case Call::Role::StartTime:
 
1528
         return (int) m_pStartTimeStamp;
 
1529
      case Call::Role::StopTime:
 
1530
         return (int) m_pStopTimeStamp;
 
1531
      case Call::Role::IsRecording:
 
1532
         return isRecording();
 
1533
      case Call::Role::IsPresent:
 
1534
         return peerPhoneNumber()->isPresent();
 
1535
      case Call::Role::IsTracked:
 
1536
         return peerPhoneNumber()->isTracked();
 
1537
      case Call::Role::SupportPresence:
 
1538
         return peerPhoneNumber()->supportPresence();
 
1539
      case Call::Role::CategoryIcon:
 
1540
         return peerPhoneNumber()->category()->icon(peerPhoneNumber()->isTracked(),peerPhoneNumber()->isPresent());
 
1541
      case Call::Role::CallCount:
 
1542
         return peerPhoneNumber()->callCount();
 
1543
      case Call::Role::TotalSpentTime:
 
1544
         return peerPhoneNumber()->totalSpentTime();
 
1545
      case Call::Role::DropState:
 
1546
         return property("dropState");
 
1547
         break;
 
1548
      case Call::Role::Missed:
 
1549
         return m_Missed;
 
1550
      case Call::Role::DTMFAnimState:
 
1551
         return property("DTMFAnimState");
 
1552
         break;
 
1553
      case Call::Role::LastDTMFidx:
 
1554
         return property("latestDtmfIdx");
 
1555
         break;
 
1556
      case Call::Role::DropPosition:
 
1557
         return property("dropPosition");
 
1558
         break;
 
1559
      default:
 
1560
         break;
 
1561
   };
 
1562
   return QVariant();
 
1563
}
 
1564
 
 
1565
 
 
1566
void Call::playDTMF(const QString& str)
 
1567
{
 
1568
   Q_NOREPLY DBus::CallManager::instance().playDTMF(str);
 
1569
   emit dtmfPlayed(str);
978
1570
}