23 #include <TelepathyQt/AccountManager>
24 #include <TelepathyQt/SimpleCallObserver>
25 #include <TelepathyQt/PendingOperation>
26 #include <TelepathyQt/PendingReady>
27 #include <TelepathyQt/PendingAccount>
34 class TelepathyCallMonitor :
public QObject
38 TelepathyCallMonitor(
const Tp::AccountPtr& account):
40 mCallObserver(Tp::SimpleCallObserver::create(mAccount)) {
41 connect(mCallObserver.data(), SIGNAL(callStarted(Tp::CallChannelPtr)), SIGNAL(offHook()));
42 connect(mCallObserver.data(), SIGNAL(callEnded(Tp::CallChannelPtr,QString,QString)), SIGNAL(onHook()));
43 connect(mCallObserver.data(), SIGNAL(streamedMediaCallStarted(Tp::StreamedMediaChannelPtr)), SIGNAL(offHook()));
44 connect(mCallObserver.data(), SIGNAL(streamedMediaCallEnded(Tp::StreamedMediaChannelPtr,QString,QString)), SIGNAL(onHook()));
52 Tp::AccountPtr mAccount;
53 Tp::SimpleCallObserverPtr mCallObserver;
57 class TelepathyBridge :
public QObject
65 QTimer::singleShot(0,
this, SLOT(accountManagerSetup()));
69 for (std::list<TelepathyCallMonitor*>::iterator it = mCallMonitors.begin();
70 it != mCallMonitors.end();
77 std::lock_guard<std::mutex> l(cb_lock);
82 void accountManagerSetup() {
83 mAccountManager = Tp::AccountManager::create(Tp::AccountFactory::create(QDBusConnection::sessionBus(),
84 Tp::Account::FeatureCore),
85 Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
86 Tp::Connection::FeatureCore));
87 connect(mAccountManager->becomeReady(),
88 SIGNAL(finished(Tp::PendingOperation*)),
89 SLOT(accountManagerReady(Tp::PendingOperation*)));
92 void accountManagerReady(Tp::PendingOperation* operation) {
93 if (operation->isError()) {
94 std::cerr <<
"TelepathyBridge: Operation failed (accountManagerReady)" << std::endl;
95 QTimer::singleShot(1000,
this, SLOT(accountManagerSetup()));
99 Q_FOREACH(
const Tp::AccountPtr& account, mAccountManager->allAccounts()) {
100 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
101 SIGNAL(finished(Tp::PendingOperation*)),
102 SLOT(accountReady(Tp::PendingOperation*)));
105 connect(mAccountManager.data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(newAccount(Tp::AccountPtr)));
108 void newAccount(
const Tp::AccountPtr& account)
110 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
111 SIGNAL(finished(Tp::PendingOperation*)),
112 SLOT(accountReady(Tp::PendingOperation*)));
115 void accountReady(Tp::PendingOperation* operation) {
116 if (operation->isError()) {
117 std::cerr <<
"TelepathyAccount: Operation failed (accountReady)" << std::endl;
121 Tp::PendingReady* pendingReady = qobject_cast<Tp::PendingReady*>(operation);
122 if (pendingReady == 0) {
123 std::cerr <<
"Rejecting account because could not understand ready status" << std::endl;
127 checkAndAddAccount(Tp::AccountPtr::qObjectCast(pendingReady->proxy()));
132 std::lock_guard<std::mutex> l(cb_lock);
139 std::lock_guard<std::mutex> l(cb_lock);
146 std::function<void (CallMonitor::State)> cb;
147 Tp::AccountManagerPtr mAccountManager;
148 std::list<TelepathyCallMonitor*> mCallMonitors;
150 void checkAndAddAccount(
const Tp::AccountPtr& account)
152 Tp::ConnectionCapabilities caps = account->capabilities();
156 auto tcm =
new TelepathyCallMonitor(account);
157 connect(tcm, SIGNAL(offHook()), SLOT(offHook()));
158 connect(tcm, SIGNAL(onHook()), SLOT(onHook()));
159 mCallMonitors.push_back(tcm);
170 std::thread([
this]() {
173 std::cout <<
"CallMonitor: Creating TelepathyBridge" << std::endl;
174 mBridge =
new TelepathyBridge();
179 }
catch(
const std::system_error& error) {
180 std::cerr <<
"exception(std::system_error) in CallMonitor thread start" << error.what() << std::endl;
182 std::cerr <<
"exception(...) in CallMonitor thread start" << std::endl;
185 std::unique_lock<std::mutex> lck(mtx);
186 cv.wait_for(lck, std::chrono::seconds(3));
197 std::condition_variable cv;
215 std::cout <<
"CallMonitor: Setting up callback for TelepathyBridge on_change" << std::endl;
218 std::cerr <<
"TelepathyBridge: Failed to hook on_change signal, bridge not yet set" << std::endl;
221 #include "call_monitor.moc"
void destroy()
Destroys the Qt core world and quits its event loop.
void build_and_run(int argc, char **argv, const std::function< void()> &ready)
Sets up the Qt core world and executes its event loop. Blocks until destroy() is called.
void on_change(const std::function< void(CallMonitor::State)> &func)
TelepathyBridge * mBridge
std::future< void > enter_with_task(const std::function< void()> &task)
Enters the Qt core world and schedules the given task for execution.