25 #include <TelepathyQt/AccountManager> 26 #include <TelepathyQt/SimpleCallObserver> 27 #include <TelepathyQt/PendingOperation> 28 #include <TelepathyQt/PendingReady> 29 #include <TelepathyQt/PendingAccount> 40 class TelepathyCallMonitor :
public QObject 44 TelepathyCallMonitor(
const Tp::AccountPtr& account):
46 mCallObserver(Tp::SimpleCallObserver::create(mAccount)) {
47 connect(mCallObserver.data(), SIGNAL(callStarted(Tp::CallChannelPtr)), SIGNAL(offHook()));
48 connect(mCallObserver.data(), SIGNAL(callEnded(Tp::CallChannelPtr,QString,QString)), SIGNAL(onHook()));
49 connect(mCallObserver.data(), SIGNAL(streamedMediaCallStarted(Tp::StreamedMediaChannelPtr)), SIGNAL(offHook()));
50 connect(mCallObserver.data(), SIGNAL(streamedMediaCallEnded(Tp::StreamedMediaChannelPtr,QString,QString)), SIGNAL(onHook()));
58 Tp::AccountPtr mAccount;
59 Tp::SimpleCallObserverPtr mCallObserver;
63 class TelepathyBridge :
public QObject 71 QTimer::singleShot(0,
this, SLOT(accountManagerSetup()));
75 for (std::list<TelepathyCallMonitor*>::iterator it = mCallMonitors.begin();
76 it != mCallMonitors.end();
82 void on_change(
const std::function<
void(media::telephony::CallMonitor::State)>& func) {
83 std::lock_guard<std::mutex> l(cb_lock);
88 void accountManagerSetup() {
89 mAccountManager = Tp::AccountManager::create(Tp::AccountFactory::create(QDBusConnection::sessionBus(),
90 Tp::Account::FeatureCore),
91 Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
92 Tp::Connection::FeatureCore));
93 connect(mAccountManager->becomeReady(),
94 SIGNAL(finished(Tp::PendingOperation*)),
95 SLOT(accountManagerReady(Tp::PendingOperation*)));
98 void accountManagerReady(Tp::PendingOperation* operation) {
99 static uint8_t retries = 0;
100 if (operation->isError()) {
101 MH_ERROR(
"TelepathyBridge: Operation failed (accountManagerReady)");
103 QTimer::singleShot(1000,
this, SLOT(accountManagerSetup()));
109 Q_FOREACH(
const Tp::AccountPtr& account, mAccountManager->allAccounts()) {
110 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
111 SIGNAL(finished(Tp::PendingOperation*)),
112 SLOT(accountReady(Tp::PendingOperation*)));
115 connect(mAccountManager.data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(newAccount(Tp::AccountPtr)));
118 void newAccount(
const Tp::AccountPtr& account)
120 connect(account->becomeReady(Tp::Account::FeatureCapabilities),
121 SIGNAL(finished(Tp::PendingOperation*)),
122 SLOT(accountReady(Tp::PendingOperation*)));
125 void accountReady(Tp::PendingOperation* operation) {
126 if (operation->isError()) {
127 MH_ERROR(
"TelepathyAccount: Operation failed (accountReady)");
131 Tp::PendingReady* pendingReady = qobject_cast<Tp::PendingReady*>(operation);
132 if (pendingReady == 0) {
133 MH_ERROR(
"Rejecting account because could not understand ready status");
137 checkAndAddAccount(Tp::AccountPtr::qObjectCast(pendingReady->proxy()));
142 std::lock_guard<std::mutex> l(cb_lock);
144 cb(media::telephony::CallMonitor::State::OffHook);
149 std::lock_guard<std::mutex> l(cb_lock);
151 cb(media::telephony::CallMonitor::State::OnHook);
156 std::function<void (media::telephony::CallMonitor::State)> cb;
157 Tp::AccountManagerPtr mAccountManager;
158 std::list<TelepathyCallMonitor*> mCallMonitors;
160 void checkAndAddAccount(
const Tp::AccountPtr& account)
162 Tp::ConnectionCapabilities caps = account->capabilities();
166 auto tcm =
new TelepathyCallMonitor(account);
167 connect(tcm, SIGNAL(offHook()), SLOT(offHook()));
168 connect(tcm, SIGNAL(onHook()), SLOT(onHook()));
169 mCallMonitors.push_back(tcm);
173 struct CallMonitor :
public media::telephony::CallMonitor
175 CallMonitor() : mBridge{
nullptr}
179 qt_world = std::move(std::thread([
this]()
185 MH_DEBUG(
"CallMonitor: Creating TelepathyBridge");
186 mBridge =
new TelepathyBridge();
191 }
catch(
const std::system_error& error) {
192 MH_ERROR(
"exception(std::system_error) in CallMonitor thread start %s", error.what());
194 MH_ERROR(
"exception(...) in CallMonitor thread start");
198 std::unique_lock<std::mutex> lck(mtx);
199 cv.wait_for(lck, std::chrono::seconds(3));
203 mBridge->on_change([
this](CallMonitor::State state)
205 call_state_changed(state);
222 if (qt_world.joinable())
226 const core::Signal<media::telephony::CallMonitor::State>& on_call_state_changed()
const 228 return call_state_changed;
231 TelepathyBridge *mBridge;
232 core::Signal<media::telephony::CallMonitor::State> call_state_changed;
234 std::thread qt_world;
236 std::condition_variable cv;
243 return std::make_shared<::impl::CallMonitor>();
246 #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.