channelDestroyed hadling, TPSESSION_DEBUG env
[tpsession] / tpsession-0.1 / tpsession / tpsession.cpp
1 /*
2  * This file is part of TpSession
3  *
4  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
5  * Contact Kate Alhola  kate.alhola(a)nokia.com
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 #include "tpsession.h"
22 #include <QDebug>
23
24
25
26
27
28 /**
29  * \class TpSession
30  * \headerfile <tpsession.h>
31  *
32  * Top level class, counterpart of Account Manager. TpSession connects to account manager and requests accounts from it. TpSession creates TpSessionAccount for all accounts .
33  * As top level class TpSession provides simÃ¥lified interface to send and receive messages via any account. TpSession provides signal when it has accounts ready.
34  * If you require some specific account in constructor, you will receive signal only when this account is ready. If you use constructor without any parameters, you will get one
35  * signal for every account.  If synchronous is true, constructor is executed as synchronous and it does return after transactions to set up accounts are done.
36  */
37 /**
38  * \fn void TpSession::accountReady(TpSessionAccount *);
39  *
40  * Emitted when the account becomes ready
41  *
42  * \param  TpSessionAccount  pointer to account become ready
43  */
44 /**
45  * \fn void TpSession::amReady(TpSession *);
46  *
47  * Emitted when the account Manager becomes ready
48  *
49  * \param  TpSession  pointer to TpSession class
50  */
51 /**
52  * \fn void TpSession::messageReceived(const Tp::ReceivedMessage &,TpSessionAccount *);
53  *
54  * Emitted when any of Account Managers recived message
55  *
56  * \param  Tp::ReceivedMessage  Message received
57  * \param  TpSessionAccount  pointer to account received message
58  */
59
60
61 /**
62  * Construct a new TpSession object.
63  *
64  * \param cmname      Name of the default connection manager. Can be empty or omnitted, then there is no default connection manager
65  * \param synchronous if false, asynchronous behavior, function returns immediately and accountReady signals are emitted when accounts are ready
66  *                    if True, synchronous behavior and function returns when accounts are ready
67  */
68 TpSession::TpSession(QString cmname,bool synchronous)
69 {
70     Tp::registerTypes();
71     Tp::enableDebug(false);
72     Tp::enableWarnings(false);
73
74     QProcessEnvironment env;
75     tpsdebug=env.systemEnvironment().contains("TPSESSION_DEBUG");
76     if(tpsdebug) qDebug() << "Tpsession debug:" << tpsDebug();
77
78     mAM = Tp::AccountManager::create();
79     reqCm=cmname;
80     sync=synchronous;
81     connect(mAM->becomeReady(),
82             SIGNAL(finished(Tp::PendingOperation *)),
83             SLOT(onAMReady(Tp::PendingOperation *)));
84     connect(mAM.data(),
85             SIGNAL(accountCreated(const QString &)),
86             SLOT(onAccountCreated(const QString &)));
87
88    // createObserver();
89   if(synchronous) loop.exec(); // Loop locally untill accounts are initialized
90    reqCm=cmname;
91
92 }
93 TpSession* TpSession::instancePtr=NULL;
94 bool TpSession::tpsdebug=false;
95 /**
96  * Returns pointer to TpSession singleton. If there is not yet TpSession Object, creates it with "Ring" connection manager as default
97  *
98  * \param synchronous if false, asynchronous behavior, function returns immediately and accountReady signals are emitted when accounts are ready
99  *                    if True, synchronous behavior and function returns when accounts are ready
100  */
101 TpSession* TpSession::instance(bool synchronous)
102 {
103     if(instancePtr==NULL) instancePtr=new TpSession("ring",synchronous);
104     return instancePtr;
105 };
106
107 bool TpSession::tpsDebug()
108 {
109     return tpsdebug;
110 }
111
112 void TpSession::onAMReady(Tp::PendingOperation *op)
113 {
114  Q_UNUSED(op);
115   // qDebug() << "TpSession::onAMReady";
116  TpSessionAccount *tpacc;
117
118    foreach (const QString &path, mAM->allAccountPaths()) {
119        accounts+=tpacc=new TpSessionAccount(mAM, path);
120        connect(tpacc,SIGNAL(accountReady(TpSessionAccount*)),
121                       SLOT(onAccountReady(TpSessionAccount *)));
122     }
123
124 }
125
126 void TpSession::onReady(Tp::PendingOperation *)
127 {
128 };
129
130 void TpSession::onAccountCreated(const QString &path)
131 {
132
133     accounts+=new TpSessionAccount(mAM, path);
134 }
135
136 void TpSession::onAccountReady(TpSessionAccount *tpacc)
137 {
138   //qDebug() << "TpSession::onAccountReady:Account " << tpacc->acc->cmName() << "is Ready sync=" << sync << "waiting:" << reqCm;
139   connect(tpacc,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionAccount *)),
140                   SLOT(onMessageReceived(const Tp::ReceivedMessage &,TpSessionAccount *)));
141   if(!reqCm.isEmpty() && tpacc->acc->cmName()==reqCm) {
142     if(sync) {
143         sync=false;
144         loop.quit();
145         qDebug() << "sync eventloop exit";
146     }
147      emit accountReady(tpacc);
148      if(!reqMsg.isEmpty()) tpacc->sendMessageToAddress(reqAddress,reqMsg);
149   }
150 }
151
152 void TpSession::onMessageReceived(const Tp::ReceivedMessage &msg,TpSessionAccount *acc)
153 {
154   //    qDebug() << "TestProg::onMessageReceived " << msg.text() << "from " << msg.sender()->id();
155     emit messageReceived(msg,acc);
156 }
157
158 /**
159  * Send message using specified connection manager to address
160  *
161  * \param connectionMgr  Name of the connection manager
162  * \param address Valid address for this connection manager type. Asexample telephone number to Ring, GoogleTalk address for Gabble
163  * \param message Message body
164  */
165 void TpSession::sendMessageToAddress(QString connectionMgr,QString address,QString message)
166 {
167  TpSessionAccount *tpsa=getAccount(connectionMgr);
168  if(tpsa) tpsa->sendMessageToAddress(address,message);
169 }
170 /**
171  * Returns pointer to TpSessionAccout object with specified connection manager or protocol, returns NULL if no match found
172  *
173  * \param cm  Name of the connection manager, or iniqueIdentifier (dbus path  to cm) if left empty matches every entry
174  * \param protocol Name of the protocol manager, if left empty matches every entry
175  */
176 TpSessionAccount* TpSession::getAccount(const  QString cm,QString protocol)
177 {
178   // qDebug() << "TpSession::getAccount" << cm << " " << protocol;
179  foreach (TpSessionAccount *tpacc, accounts) {
180    if((!cm.isEmpty()  && ((tpacc->acc->cmName()==cm) || (tpacc->acc->uniqueIdentifier()==cm))) || (!protocol.isEmpty() && tpacc->acc->protocol()==protocol)) {
181      //     qDebug() << "TpSession::getAccount found" << tpacc->acc->cmName() << " " << tpacc->acc->protocol() << " " << tpacc->acc->uniqueIdentifier();
182      return tpacc;
183      }
184  }
185  return NULL;
186 }
187
188 void TpSession::createObserver()
189 {
190
191       qDebug() << __PRETTY_FUNCTION__ ;
192
193     registrar = Tp::ClientRegistrar::create();
194
195     Tp::ChannelClassList channelFilters;
196     QMap<QString, QDBusVariant> textFilter, mediaFilter;
197     // Registering Text channel observer
198     textFilter.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
199                   QDBusVariant(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
200     textFilter.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
201                   QDBusVariant(Tp::HandleTypeContact));
202     channelFilters.append(textFilter);
203
204     // Registering Media channel observer
205     mediaFilter.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
206                   QDBusVariant(TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA));
207     mediaFilter.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
208                   QDBusVariant(Tp::HandleTypeContact));
209     channelFilters.append(mediaFilter);
210
211     TpSessionObserver* observer = new TpSessionObserver( channelFilters, this );
212     bool registered = registrar->registerClient(
213       Tp::AbstractClientPtr::dynamicCast(Tp::SharedPtr<TpSessionObserver>(observer)),
214       "TpSessionChannelObserver");
215     qDebug() << "TpSession::createObserver" << (registered ? "started" : "failed");
216
217 }
218
219
220 void TpSession::createChannelListener(const QString &channelType,
221                                    const Tp::MethodInvocationContextPtr<> &context,
222                                    const Tp::AccountPtr &account,
223                                    const Tp::ChannelPtr &channel)
224 {
225     Q_UNUSED(context);
226     Q_UNUSED(account);
227     qDebug() << "TpSession::createChannelListener";
228
229     QString channelObjectPath = channel->objectPath();
230
231
232     if ( channels.contains( channelObjectPath ) &&
233          !channelType.isEmpty() &&
234          !channelObjectPath.isEmpty() ) {
235         qDebug() << "TELEPATHY_ERROR_INVALID_ARGUMENT";
236         return;
237     }
238     qDebug() << "creating listener for: " << channelObjectPath << " type " << channelType;
239 #if 0
240     ChannelListener* listener = 0;
241     if( channelType == TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT ) {
242         listener = new TextChannelListener(account, channel, context);
243     } else if ( channelType == TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA ) {
244         listener = new StreamChannelListener(account, channel, context);
245     }
246
247     if(listener) {
248         connect(listener, SIGNAL(channelClosed(ChannelListener *)),
249                 this, SLOT(channelClosed(ChannelListener *)));
250         Channels.append( channelObjectPath );
251     }
252 #endif
253 }
254
255
256
257
258
259
260
261