23 #include <TelepathyQt/AccountManager>
24 #include <TelepathyQt/SimpleCallObserver>
25 #include <TelepathyQt/PendingOperation>
26 #include <TelepathyQt/PendingReady>
27 #include <TelepathyQt/PendingAccount>
38 class TelepathyCallMonitor :
public QObject
42 TelepathyCallMonitor(
const Tp::AccountPtr& account):
44 mCallObserver(Tp::SimpleCallObserver::create(mAccount)) {
45 connect(mCallObserver.data(), SIGNAL(callStarted(Tp::CallChannelPtr)), SIGNAL(offHook()));
46 connect(mCallObserver.data(), SIGNAL(callEnded(Tp::CallChannelPtr,QString,QString)), SIGNAL(onHook()));
47 connect(mCallObserver.data(), SIGNAL(streamedMediaCallStarted(Tp::StreamedMediaChannelPtr)), SIGNAL(offHook()));
48 connect(mCallObserver.data(), SIGNAL(streamedMediaCallEnded(Tp::StreamedMediaChannelPtr,QString,QString)), SIGNAL(onHook()));
56 Tp::AccountPtr mAccount;
57 Tp::SimpleCallObserverPtr mCallObserver;
61 class TelepathyBridge :
public QObject
69 QTimer::singleShot(0,
this, SLOT(accountManagerSetup()));
73 for (std::list<TelepathyCallMonitor*>::iterator it = mCallMonitors.begin();
74 it != mCallMonitors.end();
80 void on_change(
const std::function<
void(media::telephony::CallMonitor::State)>& func) {
81 std::lock_guard<std::mutex> l(cb_lock);
86 void accountManagerSetup() {
87 mAccountManager = Tp::AccountManager::create(Tp::AccountFactory::create(QDBusConnection::sessionBus(),
88 Tp::Account::FeatureCore),
89 Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
90 Tp::Connection::FeatureCore));
91 connect(mAccountManager->becomeReady(),
92 SIGNAL(finished(Tp::PendingOperation*)),
93 SLOT(accountManagerReady(Tp::PendingOperation*)));
96 void accountManagerReady(Tp::PendingOperation* operation) {
97 if (operation->isError()) {
98 std::cerr <<
"TelepathyBridge: Operation failed (accountManagerReady)" << std::endl;
99 QTimer::singleShot(1000,
this, SLOT(accountManagerSetup()));
103 Q_FOREACH(
const Tp::AccountPtr& account, mAccountManager->allAccounts()) {
104 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
105 SIGNAL(finished(Tp::PendingOperation*)),
106 SLOT(accountReady(Tp::PendingOperation*)));
109 connect(mAccountManager.data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(newAccount(Tp::AccountPtr)));
112 void newAccount(
const Tp::AccountPtr& account)
114 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
115 SIGNAL(finished(Tp::PendingOperation*)),
116 SLOT(accountReady(Tp::PendingOperation*)));
119 void accountReady(Tp::PendingOperation* operation) {
120 if (operation->isError()) {
121 std::cerr <<
"TelepathyAccount: Operation failed (accountReady)" << std::endl;
125 Tp::PendingReady* pendingReady = qobject_cast<Tp::PendingReady*>(operation);
126 if (pendingReady == 0) {
127 std::cerr <<
"Rejecting account because could not understand ready status" << std::endl;
131 checkAndAddAccount(Tp::AccountPtr::qObjectCast(pendingReady->proxy()));
136 std::lock_guard<std::mutex> l(cb_lock);
138 cb(media::telephony::CallMonitor::State::OffHook);
143 std::lock_guard<std::mutex> l(cb_lock);
145 cb(media::telephony::CallMonitor::State::OnHook);
150 std::function<void (media::telephony::CallMonitor::State)> cb;
151 Tp::AccountManagerPtr mAccountManager;
152 std::list<TelepathyCallMonitor*> mCallMonitors;
154 void checkAndAddAccount(
const Tp::AccountPtr& account)
156 Tp::ConnectionCapabilities caps = account->capabilities();
160 auto tcm =
new TelepathyCallMonitor(account);
161 connect(tcm, SIGNAL(offHook()), SLOT(offHook()));
162 connect(tcm, SIGNAL(onHook()), SLOT(onHook()));
163 mCallMonitors.push_back(tcm);
167 struct CallMonitor :
public media::telephony::CallMonitor
169 CallMonitor() : mBridge{
nullptr}
173 qt_world = std::move(std::thread([
this]()
179 std::cout <<
"CallMonitor: Creating TelepathyBridge" << std::endl;
180 mBridge =
new TelepathyBridge();
185 }
catch(
const std::system_error& error) {
186 std::cerr <<
"exception(std::system_error) in CallMonitor thread start" << error.what() << std::endl;
188 std::cerr <<
"exception(...) in CallMonitor thread start" << std::endl;
192 std::unique_lock<std::mutex> lck(mtx);
193 cv.wait_for(lck, std::chrono::seconds(3));
197 mBridge->on_change([
this](CallMonitor::State state)
199 call_state_changed(state);
216 if (qt_world.joinable())
220 const core::Signal<media::telephony::CallMonitor::State>& on_call_state_changed()
const
222 return call_state_changed;
225 TelepathyBridge *mBridge;
226 core::Signal<media::telephony::CallMonitor::State> call_state_changed;
228 std::thread qt_world;
230 std::condition_variable cv;
237 return std::make_shared<impl::CallMonitor>();
240 #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.
std::future< void > enter_with_task(const std::function< void()> &task)
Enters the Qt core world and schedules the given task for execution.