Commit ec2f1ebe authored by Guillaume Roguez's avatar Guillaume Roguez

Merge branch 'wip/nodejs' into 'master'

* wip/nodejs:
  added correct newCallCreated callback
  nodejs: callbacks get queued to run on main loop
  nodejs: added data structure conversions and more callbacks
  nodejs: fix build error
  nodejs: created RingDaemon JS Class
  Added Typemaps to handle Callbacks
  nodejs: added more callbacks
  nodejs: implement two Javascript callbacks
  bin: allow to build multiple subdirs
  nodejs: build with ring
  nodejs: build module after generating bindings
  update for latest daemon API changes
  remove unneeded file
  fix include
  gyp: link with dring
  Included dring source directory in binding.gyp file
  nodejs: add initial module

Change-Id: Ia9df106109531d6f27b0621c3d2ee433ee3460fc
parents c92175c7 7c11d095
......@@ -18,8 +18,10 @@ ringcli_CXXFLAGS = -I$(top_srcdir)/src \
ringcli_LDADD = $(top_builddir)/src/libring.la
endif
SUBDIRS=
if RING_DBUS
SUBDIRS=dbus
SUBDIRS+=dbus
ringlib_PROGRAMS = dring
......@@ -32,8 +34,12 @@ dring_CXXFLAGS= -I$(top_srcdir)/src ${DBUSCPP_CFLAGS} \
dring_LDADD = dbus/libclient_dbus.la ${DBUSCPP_LIBS} $(top_builddir)/src/libring.la
endif
if RING_NODEJS
SUBDIRS+=nodejs
endif
if RING_RESTCPP
SUBDIRS=restcpp
SUBDIRS+=restcpp
sbin_PROGRAMS = restdring
......
include $(top_srcdir)/globals.mk
BUILT_SOURCES= \
ring_wrapper.cpp \
build/Makefile \
build/Release/obj.target/dring.node
ring_wrapper.cpp: nodejs_interface.i configurationmanager.i managerimpl.i
$(SWIG) -v -c++ -javascript -node -o ring_wrapper.cpp nodejs_interface.i
build/Makefile: ring_wrapper.cpp binding.gyp
node-gyp configure
build/Release/obj.target/dring.node: build/Makefile ring_wrapper.cpp callback.h
node-gyp build
CLEANFILES= \
$(BUILT_SOURCES) \
build/Release/dring.node
{
"targets": [
{
"target_name": "dring",
"sources": [ "ring_wrapper.cpp" ],
'include_dirs': ['../../src/'],
'libraries': ['-L<(module_root_dir)/../../src/.libs/', '-lring'],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ]
}
]
}
\ No newline at end of file
#pragma once
#define V8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str.data(), v8::String::kNormalString, str.size())
#include <uv.h>
#include <queue>
#include <functional>
#include <mutex>
using namespace v8;
Persistent<Function> accountsChangedCb;
Persistent<Function> registrationStateChangedCb;
Persistent<Function> volatileDetailsChangedCb;
Persistent<Function> incomingAccountMessageCb;
Persistent<Function> accountMessageStatusChangedCb;
Persistent<Function> incomingTrustRequestCb;
Persistent<Function> contactAddedCb;
Persistent<Function> contactRemovedCb;
Persistent<Function> exportOnRingEndedCb;
Persistent<Function> nameRegistrationEndedCb;
Persistent<Function> knownDevicesChangedCb;
Persistent<Function> registeredNameFoundCb;
Persistent<Function> callStateChangedCb;
Persistent<Function> incomingMessageCb;
Persistent<Function> incomingCallCb;
Persistent<Function> newCallCreatedCb;
std::queue<std::function<void() >> pendingSignals;
std::mutex pendingSignalsLock;
uv_async_t signalAsync;
Persistent<Function>* getPresistentCb(const std::string &signal) {
if (signal == "AccountsChanged")
return &accountsChangedCb;
else if (signal == "RegistrationStateChanged")
return &registrationStateChangedCb;
else if (signal == "VolatileDetailsChanged")
return &volatileDetailsChangedCb;
else if (signal == "IncomingAccountMessage")
return &incomingAccountMessageCb;
else if (signal == "AccountMessageStatusChanged")
return &accountMessageStatusChangedCb;
else if (signal == "IncomingTrustRequest")
return &incomingTrustRequestCb;
else if (signal == "ContactAdded")
return &contactAddedCb;
else if (signal == "ContactRemoved")
return &contactRemovedCb;
else if (signal == "ExportOnRingEnded")
return &exportOnRingEndedCb;
else if (signal == "NameRegistrationEnded")
return &nameRegistrationEndedCb;
else if (signal == "KnownDevicesChanged")
return &knownDevicesChangedCb;
else if (signal == "RegisteredNameFound")
return &registeredNameFoundCb;
else if (signal == "CallStateChanged")
return &callStateChangedCb;
else if (signal == "IncomingMessage")
return &incomingMessageCb;
else if (signal == "IncomingCall")
return &incomingCallCb;
else if (signal == "NewCallCreated")
return &newCallCreatedCb;
else return nullptr;
}
void intVectToJsArray(const std::vector<uint8_t>& intVect, const Local<Array>& jsArray) {
for (unsigned int i = 0; i < intVect.size(); i++)
jsArray->Set(SWIGV8_INTEGER_NEW_UNS(i), SWIGV8_INTEGER_NEW(intVect[i]));
}
void stringMapToJsMap(const std::map<std::string, std::string>& strmap, const Local<Object> &jsMap) {
for (auto& kvpair : strmap)
jsMap->Set(V8_STRING_NEW(std::get<0>(kvpair)), V8_STRING_NEW(std::get<1>(kvpair)));
}
void setCallback(const std::string& signal, Local<Function>& func) {
if (auto* presistentCb = getPresistentCb(signal)) {
if (func->IsObject() && func->IsFunction()) {
presistentCb->Reset(Isolate::GetCurrent(), func);
} else {
presistentCb->Reset();
}
} else {
printf("No Signal Associated with Event \'%s\'\n", signal.c_str());
}
}
void parseCbMap(const Local<Value>& callbackMap) {
Local<Object> cbAssocArray = callbackMap->ToObject();
Local<Array> props = cbAssocArray->GetOwnPropertyNames();
for (uint32_t i = 0; i < props->Length(); ++i) {
const Local<Value> key_local = props->Get(i);
std::string key = *String::Utf8Value(key_local);
Handle<Object> buffer = cbAssocArray->Get(V8_STRING_NEW(key))->ToObject();
Local<Function> func = Local<Function>::Cast(buffer);
setCallback(key, func);
}
}
void handlePendingSignals(uv_async_t* async_data) {
SWIGV8_HANDLESCOPE();
std::lock_guard<std::mutex> lock(pendingSignalsLock);
while (not pendingSignals.empty()) {
pendingSignals.front()();
pendingSignals.pop();
}
}
void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, state, code, detail_str]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), registrationStateChangedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(state), SWIGV8_INTEGER_NEW(code), V8_STRING_NEW(detail_str)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 4, callback_args);
}
});
uv_async_send(&signalAsync);
}
void volatileDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, details]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), volatileDetailsChangedCb);
if (!func.IsEmpty()) {
Local<Object> jsMap = SWIGV8_OBJECT_NEW();
stringMapToJsMap(details, jsMap);
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), jsMap};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 2, callback_args);
}
});
uv_async_send(&signalAsync);
}
void accountsChanged() {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), accountsChangedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 0, callback_args);
}
});
uv_async_send(&signalAsync);
}
void contactAdded(const std::string& account_id, const std::string& uri, bool confirmed) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, uri, confirmed]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), contactAddedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(uri), SWIGV8_BOOLEAN_NEW(confirmed)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void contactRemoved(const std::string& account_id, const std::string& uri, bool banned) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, uri, banned]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), contactRemovedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(uri), SWIGV8_BOOLEAN_NEW(banned)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void exportOnRingEnded(const std::string& account_id, int state, const std::string& pin) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, state, pin]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), exportOnRingEndedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), SWIGV8_INTEGER_NEW(state), V8_STRING_NEW(pin)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void nameRegistrationEnded(const std::string& account_id, int state, const std::string& name) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, state, name]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), nameRegistrationEndedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), SWIGV8_INTEGER_NEW(state), V8_STRING_NEW(name)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void registeredNameFound(const std::string& account_id, int state, const std::string& address, const std::string& name) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, state, address, name]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), registeredNameFoundCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), SWIGV8_INTEGER_NEW(state), V8_STRING_NEW(address), V8_STRING_NEW(name)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 4, callback_args);
}
});
uv_async_send(&signalAsync);
}
void accountMessageStatusChanged(const std::string& account_id, uint64_t message_id, const std::string& to, int state) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, message_id, to, state]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), accountMessageStatusChangedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), SWIGV8_INTEGER_NEW_UNS(message_id), V8_STRING_NEW(to), SWIGV8_INTEGER_NEW(state)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 4, callback_args);
}
});
uv_async_send(&signalAsync);
}
void incomingAccountMessage(const std::string& account_id, const std::string& from, const std::map<std::string, std::string>& payloads) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, from, payloads]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), incomingAccountMessageCb);
if (!func.IsEmpty()) {
Local<Object> jsMap = SWIGV8_OBJECT_NEW();
stringMapToJsMap(payloads, jsMap);
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(from), jsMap};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void knownDevicesChanged(const std::string& account_id, const std::map<std::string, std::string>& devices) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, devices]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), knownDevicesChangedCb);
if (!func.IsEmpty()) {
Local<Object> jsMap = SWIGV8_OBJECT_NEW();
stringMapToJsMap(devices, jsMap);
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), jsMap};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 2, callback_args);
}
});
uv_async_send(&signalAsync);
}
void incomingTrustRequest(const std::string& account_id, const std::string& from, const std::vector<uint8_t>& payload, time_t received) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, from, payload, received]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), incomingTrustRequestCb);
if (!func.IsEmpty()) {
Local<Array> jsArray = SWIGV8_ARRAY_NEW();
intVectToJsArray(payload, jsArray);
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(from), jsArray, SWIGV8_NUMBER_NEW(received)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 4, callback_args);
}
});
uv_async_send(&signalAsync);
}
void callStateChanged(const std::string& call_id, const std::string& state, int detail_code) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([call_id, state, detail_code]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), callStateChangedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(call_id), V8_STRING_NEW(state), SWIGV8_INTEGER_NEW(detail_code)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void incomingMessage(const std::string& id, const std::string& from, const std::map<std::string, std::string>& messages) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([id, from, messages]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), incomingMessageCb);
if (!func.IsEmpty()) {
Local<Object> jsMap = SWIGV8_OBJECT_NEW();
stringMapToJsMap(messages, jsMap);
Local<Value> callback_args[] = {V8_STRING_NEW(id), V8_STRING_NEW(from), jsMap};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 4, callback_args);
}
});
uv_async_send(&signalAsync);
}
void incomingCall(const std::string& account_id, const std::string& call_id, const std::string& from) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, call_id, from]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), incomingCallCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(call_id), V8_STRING_NEW(from)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
void newCallCreated(const std::string& account_id, const std::string& call_id, const std::string& to_uri) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, call_id, to_uri]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), newCallCreatedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW(account_id), V8_STRING_NEW(call_id), V8_STRING_NEW(to_uri)};
func->Call(SWIGV8_CURRENT_CONTEXT()->Global(), 3, callback_args);
}
});
uv_async_send(&signalAsync);
}
\ No newline at end of file
/*
* Copyright (C) 2004-2016 Savoir-faire Linux Inc.
*
* Author: Emeric Vigier <emeric.vigier@savoirfairelinux.com>
* Alexandre Lision <alexnadre.L@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
%header %{
#include "dring/dring.h"
#include "dring/callmanager_interface.h"
class Callback {
public:
virtual ~Callback() {}
virtual void callStateChanged(const std::string& call_id, const std::string& state, int detail_code){}
virtual void transferFailed(void){}
virtual void transferSucceeded(void){}
virtual void recordPlaybackStopped(const std::string& path){}
virtual void voiceMailNotify(const std::string& call_id, int nd_msg){}
virtual void incomingMessage(const std::string& id, const std::string& from, const std::map<std::string, std::string>& messages){}
virtual void incomingCall(const std::string& account_id, const std::string& call_id, const std::string& from){}
virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){}
virtual void conferenceCreated(const std::string& conf_id){}
virtual void conferenceChanged(const std::string& conf_id, const std::string& state){}
virtual void conferenceRemoved(const std::string& conf_id){}
virtual void newCallCreated(const std::string& call_id, const std::string&, const std::string&){}
virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){}
virtual void conferenceRemove(const std::string& conf_id){}
virtual void newCall(const std::string& account_id, const std::string& call_id, const std::string& to){}
virtual void sipCallStateChange(const std::string& call_id, const std::string& state, int code){}
virtual void recordingStateChanged(const std::string& call_id, int code){}
virtual void recordStateChange(const std::string& call_id, int state){}
virtual void onRtcpReportReceived(const std::string& call_id, const std::map<std::string, int>& stats){}
virtual void peerHold(const std::string& call_id, bool holding){}
};
%}
%feature("director") Callback;
namespace DRing {
/* Call related methods */
std::string placeCall(const std::string& accountID, const std::string& to);
bool refuse(const std::string& callID);
bool accept(const std::string& callID);
bool hangUp(const std::string& callID);
bool hold(const std::string& callID);
bool unhold(const std::string& callID);
bool muteLocalMedia(const std::string& callid, const std::string& mediaType, bool mute);
bool transfer(const std::string& callID, const std::string& to);
bool attendedTransfer(const std::string& transferID, const std::string& targetID);
std::map<std::string, std::string> getCallDetails(const std::string& callID);
std::vector<std::string> getCallList();
/* Conference related methods */
void removeConference(const std::string& conference_id);
bool joinParticipant(const std::string& sel_callID, const std::string& drag_callID);
void createConfFromParticipantList(const std::vector<std::string>& participants);
bool isConferenceParticipant(const std::string& call_id);
bool addParticipant(const std::string& callID, const std::string& confID);
bool addMainParticipant(const std::string& confID);
bool detachParticipant(const std::string& callID);
bool joinConference(const std::string& sel_confID, const std::string& drag_confID);
bool hangUpConference(const std::string& confID);
bool holdConference(const std::string& confID);
bool unholdConference(const std::string& confID);
std::vector<std::string> getConferenceList();
std::vector<std::string> getParticipantList(const std::string& confID);
std::vector<std::string> getDisplayNames(const std::string& confID);
std::string getConferenceId(const std::string& callID);
std::map<std::string, std::string> getConferenceDetails(const std::string& callID);
/* File Playback methods */
bool startRecordedFilePlayback(const std::string& filepath);
void stopRecordedFilePlayback(const std::string& filepath);
/* General audio methods */
bool toggleRecording(const std::string& callID);
/* DEPRECATED */
void setRecording(const std::string& callID);
void recordPlaybackSeek(double value);
bool getIsRecording(const std::string& callID);
std::string getCurrentAudioCodecName(const std::string& callID);
void playDTMF(const std::string& key);
void startTone(int32_t start, int32_t type);
bool switchInput(const std::string& callID, const std::string& resource);
/* Instant messaging */
void sendTextMessage(const std::string& callID, const std::map<std::string, std::string>& messages, const std::string& from, const bool& isMixed);
}
class Callback {
public:
virtual ~Callback() {}
virtual void callStateChanged(const std::string& call_id, const std::string& state, int detail_code){}
virtual void transferFailed(void){}
virtual void transferSucceeded(void){}
virtual void recordPlaybackStopped(const std::string& path){}
virtual void voiceMailNotify(const std::string& call_id, int nd_msg){}
virtual void incomingMessage(const std::string& id, const std::string& from, const std::map<std::string, std::string>& messages){}
virtual void incomingCall(const std::string& account_id, const std::string& call_id, const std::string& from){}
virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){}
virtual void conferenceCreated(const std::string& conf_id){}
virtual void conferenceChanged(const std::string& conf_id, const std::string& state){}
virtual void conferenceRemoved(const std::string& conf_id){}
virtual void newCallCreated(const std::string& call_id, const std::string&, const std::string&){}
virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){}
virtual void conferenceRemove(const std::string& conf_id){}
virtual void newCall(const std::string& account_id, const std::string& call_id, const std::string& to){}
virtual void sipCallStateChange(const std::string& call_id, const std::string& state, int code){}
virtual void recordingStateChanged(const std::string& call_id, int code){}
virtual void recordStateChange(const std::string& call_id, int state){}
virtual void onRtcpReportReceived(const std::string& call_id, const std::map<std::string, int>& stats){}
virtual void peerHold(const std::string& call_id, bool holding){}
};
/*
* Copyright (C) 2004-2016 Savoir-faire Linux Inc.
*
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
%header %{
#include "dring/dring.h"
#include "dring/configurationmanager_interface.h"
class ConfigurationCallback {
public:
virtual ~ConfigurationCallback(){}
virtual void volumeChanged(const std::string& device, int value){}
virtual void accountsChanged(void){}
virtual void historyChanged(void){}
virtual void stunStatusFailure(const std::string& account_id){}
virtual void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str){}
virtual void volatileAccountDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details){}
virtual void incomingAccountMessage(const std::string& /*account_id*/, const std::string& /*from*/, const std::map<std::string, std::string>& /*payload*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, uint64_t /*message_id*/, const std::string& /*to*/, int /*state*/){}
virtual void knownDevicesChanged(const std::string& /*account_id*/, const std::map<std::string, std::string>& /*devices*/){}
virtual void exportOnRingEnded(const std::string& /*account_id*/, int /*state*/, const std::string& /*pin*/){}
virtual void incomingTrustRequest(const std::string& /*account_id*/, const std::string& /*from*/, const std::vector<uint8_t>& /*payload*/, time_t received){}
virtual void contactAdded(const std::string& /*account_id*/, const std::string& /*uri*/, bool confirmed){}
virtual vo