summaryrefslogtreecommitdiffstats
path: root/ahl-binding
diff options
context:
space:
mode:
Diffstat (limited to 'ahl-binding')
-rw-r--r--ahl-binding/ahl-binding.cpp92
-rw-r--r--ahl-binding/ahl-binding.hpp6
-rw-r--r--ahl-binding/role.cpp40
3 files changed, 118 insertions, 20 deletions
diff --git a/ahl-binding/ahl-binding.cpp b/ahl-binding/ahl-binding.cpp
index 036ed88..98d36b6 100644
--- a/ahl-binding/ahl-binding.cpp
+++ b/ahl-binding/ahl-binding.cpp
@@ -89,6 +89,24 @@ void ahl_api_get_roles(afb_req_t req)
}
/**
+ * @brief Callback invoked when clients call the verb 'subscribe'.
+ * @param[in] req Request to handle.
+ */
+void ahl_api_subscribe(afb_req_t req)
+{
+ ahl_binding_t::instance().subscribe(req);
+}
+
+/**
+ * @brief Callback invoked when clients call the verb 'unsubscribe'.
+ * @param[in] req Request to handle.
+ */
+void ahl_api_unsubscribe(afb_req_t req)
+{
+ ahl_binding_t::instance().unsubscribe(req);
+}
+
+/**
* @brief Callback invoked when clients call a 'role' verb.
* @param[in] req Request to handle.
*
@@ -166,6 +184,13 @@ int ahl_binding_t::init()
afb_api_seal(handle_);
AFB_API_NOTICE(handle_, "API is now sealed!");
+ volume_changed_ = afb_api_make_event(handle_, "volume_changed");
+ if(!afb_event_is_valid(volume_changed_))
+ {
+ AFB_API_ERROR(handle_, "Failed to create the \"volume_changed\" event!");
+ return -2;
+ }
+
if (update_streams()) return -1;
return 0;
}
@@ -283,6 +308,30 @@ void ahl_binding_t::load_static_verbs()
{
throw std::runtime_error("Failed to add 'get_role' verb to the API.");
}
+
+ if (afb_api_add_verb(
+ handle_,
+ "subscribe",
+ "Subscribe to \"volume_changed\" event",
+ ahl_api_subscribe,
+ nullptr,
+ nullptr,
+ AFB_SESSION_NONE_X2, 0))
+ {
+ throw std::runtime_error("Failed to add 'subscribe' verb to the API.");
+ }
+
+ if (afb_api_add_verb(
+ handle_,
+ "unsubscribe",
+ "Unsubscribe to \"volume_changed\" event",
+ ahl_api_unsubscribe,
+ nullptr,
+ nullptr,
+ AFB_SESSION_NONE_X2, 0))
+ {
+ throw std::runtime_error("Failed to add 'unsubscribe' verb to the API.");
+ }
}
void ahl_binding_t::load_controller_configs()
@@ -381,26 +430,51 @@ int ahl_binding_t::create_api_verb(role_t* r)
return 0;
}
-void ahl_binding_t::get_roles(afb_req_t req)
+void ahl_binding_t::get_roles(afb_req_t req) const
{
- json_bool verbose = FALSE;
- json_object* arg = afb_req_json(req);
+ json_bool verbose = FALSE;
+ json_object* arg = afb_req_json(req);
json_object* jverbose;
if (arg != nullptr)
{
- json_bool ret = json_object_object_get_ex(arg, "verbose", &jverbose);
- if (ret) verbose = json_object_get_boolean(jverbose);
+ json_bool ret = json_object_object_get_ex(arg, "verbose", &jverbose);
+ if (ret) verbose = json_object_get_boolean(jverbose);
}
json_object* result = json_object_new_array();
for(const auto& r : roles_)
- {
- if (verbose == TRUE || r.device_uri().size())
- json_object_array_add(result, json_object_new_string(r.uid().c_str()));
- }
+ {
+ if (verbose == TRUE || r.device_uri().size())
+ json_object_array_add(result, json_object_new_string(r.uid().c_str()));
+ }
afb_req_success(req, result, nullptr);
}
+void ahl_binding_t::subscribe(afb_req_t req) const
+{
+ if (afb_req_subscribe(req, volume_changed_))
+ afb_req_fail(req, "Failed to subscribe to \"volume_changed\" event!", nullptr);
+ else
+ afb_req_success(req, nullptr, "Subscribed to \"volume_changed\" event!");
+}
+
+void ahl_binding_t::unsubscribe(afb_req_t req) const
+{
+ if (afb_req_unsubscribe(req, volume_changed_))
+ afb_req_fail(req, "Failed to unsubscribe from \"volume_changed\" event!", nullptr);
+ else
+ afb_req_success(req, nullptr, "Unsubscribed from \"volume_changed\" event!");
+}
+
+int ahl_binding_t::emit_volume_changed(const std::string& role, int volume) const
+{
+ json_object* data = json_object_new_object();
+ json_object_object_add(data, "role", json_object_new_string(role.c_str()));
+ json_object_object_add(data, "volume", json_object_new_int(volume));
+
+ return afb_event_push(volume_changed_, data);
+}
+
const std::vector<role_t> ahl_binding_t::roles() const
{
return roles_;
diff --git a/ahl-binding/ahl-binding.hpp b/ahl-binding/ahl-binding.hpp
index 0e7bd63..24f4acb 100644
--- a/ahl-binding/ahl-binding.hpp
+++ b/ahl-binding/ahl-binding.hpp
@@ -40,6 +40,7 @@ class ahl_binding_t
private:
afb_api_t handle_;
+ afb_event_t volume_changed_;
std::vector<role_t> roles_;
explicit ahl_binding_t();
@@ -60,7 +61,10 @@ public:
int preinit(afb_api_t handle);
int init();
void event(std::string name, json_object* arg);
- void get_roles(afb_req_t req);
+ void get_roles(afb_req_t req) const;
+ void subscribe(afb_req_t req) const;
+ void unsubscribe(afb_req_t req) const;
+ int emit_volume_changed(const std::string& role, int volume) const;
const std::vector<role_t> roles() const;
afb_api_t handle() const;
diff --git a/ahl-binding/role.cpp b/ahl-binding/role.cpp
index 06caa98..7d35889 100644
--- a/ahl-binding/role.cpp
+++ b/ahl-binding/role.cpp
@@ -229,18 +229,18 @@ void role_t::close(afb_req_t r, json_object* o)
}
void role_t::mute(afb_req_t r, json_object* o) {
- do_mute(r, true);
+ do_mute(r, true);
}
void role_t::unmute(afb_req_t r, json_object *o) {
- do_mute(r, false);
+ do_mute(r, false);
}
void role_t::do_mute(afb_req_t r, bool v) {
- json_object* a = json_object_new_object();
+ json_object* a = json_object_new_object();
json_object_object_add(a, "mute", json_object_new_boolean(v));
- afb_api_t api = ahl_binding_t::instance().handle();
+ afb_api_t api = ahl_binding_t::instance().handle();
afb_api_call(
api,
@@ -260,9 +260,15 @@ void role_t::do_mute(afb_req_t r, bool v) {
afb_req_addref(r));
}
+struct volumeclosure
+{
+ std::string role;
+ afb_req_t req;
+};
+
void role_t::volume(afb_req_t r, json_object* o)
{
- afb_api_t api = ahl_binding_t::instance().handle();
+ afb_api_t api = ahl_binding_t::instance().handle();
if(!afb_req_has_permission(r, "urn:AGL:permission::public:4a-audio-mixer"))
{
@@ -296,6 +302,10 @@ void role_t::volume(afb_req_t r, json_object* o)
json_object* a = json_object_new_object();
json_object_object_add(a, "volume", value);
+ volumeclosure* userdata = new volumeclosure();
+ userdata->role = uid_;
+ userdata->req = afb_req_addref(r);
+
afb_api_call(
api,
hal_.c_str(),
@@ -304,14 +314,24 @@ void role_t::volume(afb_req_t r, json_object* o)
[](void* closure, json_object* result, const char* error, const char* info, afb_api_t handle)
{
AFB_API_DEBUG(handle, "Got the following answer: %s", json_object_to_json_string(result));
- afb_req_t r = (afb_req_t)closure;
+ volumeclosure* r = reinterpret_cast<volumeclosure*>(closure);
json_object_get(result);
- if (error) afb_req_fail(r, json_object_to_json_string(result), nullptr);
- else afb_req_success(r, result, nullptr);
- afb_req_unref(r);
+ if (error) afb_req_fail(r->req, json_object_to_json_string(result), nullptr);
+ else
+ {
+ json_object* volnew;
+ if (json_object_object_get_ex(result, "volnew", &volnew))
+ {
+ ahl_binding_t::instance().emit_volume_changed(r->role, json_object_get_int(volnew));
+ }
+ afb_req_success(r->req, result, nullptr);
+ }
+ afb_req_unref(r->req);
+ delete r;
},
- afb_req_addref(r));
+ userdata
+ );
}
void role_t::interrupt(afb_req_t r, json_object* o)