10 #define UNUSED(x) (void)(x)
14 constexpr const int token_maxlen = 20;
15 constexpr const char *const wmAPI = "winman";
20 ScopeTrace(char const *func) : f(func) {
21 fprintf(stderr, "%*s%s -->\n", 2 * indent++, "", this->f);
24 fprintf(stderr, "%*s%s <--\n", 2 * --indent, "", this->f);
27 int ScopeTrace::indent = 0;
32 #define TRACE() ScopeTrace __attribute__((unused)) trace_scope_here__(__PRETTY_FUNCTION__)
35 /* called when wsj1 receives a method invocation */
36 void onCall(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
41 printf("ON-CALL %s/%s:\n%s\n", api, verb,
42 json_object_to_json_string_ext(afb_wsj1_msg_object_j(msg),
43 JSON_C_TO_STRING_PRETTY));
45 rc = afb_wsj1_reply_error_s(msg, "\"unimplemented\"", nullptr);
47 fprintf(stderr, "replying failed: %m\n");
50 /* called when wsj1 receives an event */
51 void onEvent(void *closure, const char *event, afb_wsj1_msg *msg)
55 printf("ON-EVENT %s:\n%s\n", event,
56 json_object_to_json_string_ext(afb_wsj1_msg_object_j(msg),
57 JSON_C_TO_STRING_PRETTY));
61 /* called when wsj1 hangsup */
62 void onHangup(void *closure, afb_wsj1 *wsj1)
67 printf("ON-HANGUP\n");
72 /* called when wsj1 receives a reply */
73 void onReply(void *closure, afb_wsj1_msg *msg)
76 printf("ON-REPLY %s: %s\n%s\n", (char*)closure,
77 afb_wsj1_msg_is_reply_ok(msg) ? "OK" : "ERROR",
78 json_object_to_json_string_ext(afb_wsj1_msg_object_j(msg),
79 JSON_C_TO_STRING_PRETTY));
86 AFBClient &AFBClient::instance()
93 AFBClient::AFBClient() : wsj1{}, itf{}, loop{}
96 ///* itinializing the callback interface for wsj1 */
97 itf.on_hangup = onHangup;
99 itf.on_event = onEvent;
102 AFBClient::~AFBClient()
105 sd_event_unref(loop);
109 int AFBClient::init(int port, char const *token)
112 char *uribuf = nullptr;
115 if (!token || strlen(token) > token_maxlen) {
116 fprintf(stderr, "Token is invalid\n");
121 for (char const *p = token; *p; p++) {
123 fprintf(stderr, "Token is invalid\n");
129 if (port < 1 && port > 0xffff) {
130 fprintf(stderr, "Port is invalid\n");
135 /* get the default event loop */
136 rc = sd_event_default(&loop);
138 fprintf(stderr, "Connection to default event loop failed: %s\n", strerror(-rc));
142 asprintf(&uribuf, "ws://localhost:%d/api?token=%s", port, token);
144 /* connect the websocket wsj1 to the uri given by the first argument */
145 wsj1 = afb_ws_client_connect_wsj1(loop, uribuf, &itf, nullptr);
146 if (wsj1 == nullptr) {
147 sd_event_unref(loop);
148 fprintf(stderr, "Connection to %s failed: %m\n", uribuf);
159 int AFBClient::dispatch(uint64_t timeout) {
161 return sd_event_run(loop, timeout);
164 int AFBClient::requestSurface(const char *label)
167 constexpr char const *verb = "request_surface";
169 json_object *jp = json_object_new_object();
170 json_object_object_add(jp, "drawing_name", json_object_new_string(label));
172 // std::experimental::optional look-alike
178 constexpr struct optional const nullopt = {0, true};
181 /* send the request */
182 int rc = afb_wsj1_call_j(
183 wsj1, wmAPI, verb, jp,
184 [](void *closure, afb_wsj1_msg *msg) {
185 if (afb_wsj1_msg_is_reply_ok(msg)) {
186 int id = json_object_get_int(
187 json_object_object_get(afb_wsj1_msg_object_j(msg), "response"));
188 auto oid = (optional *)closure;
191 fprintf(stderr, "wrong request surface reply received!\n");
196 fprintf(stderr, "calling %s/%s(%s) failed: %m\n", wmAPI, verb,
197 json_object_to_json_string(jp));
199 // Lets make this call sync here...
202 if (! id.is_not_set) {
204 asprintf(&buf, "%d", id.value);
205 printf("setenv(\"QT_IVI_SURFACE_ID\", %s, 1)\n", buf);
206 if (setenv("QT_IVI_SURFACE_ID", buf, 1) != 0) {
207 fprintf(stderr, "putenv failed: %m\n");
209 rc = 0; // Single point of success
212 fprintf(stderr, "Could not get surface ID from WM\n");
220 int AFBClient::activateSurface(const char *label)
224 const char begin[] = "{\"drawing_name\":\"";
225 const char end[] = "\"}";
226 const char verb[] = "activate_surface";
227 char *parameter = (char *)malloc(strlen(begin) +
230 strcpy(parameter, begin);
231 strcat(parameter, label);
232 strcat(parameter, end);
233 call(wmAPI, verb, parameter);
241 int AFBClient::deactivateSurface(const char *label)
244 json_object *j = json_object_new_object();
245 json_object_object_add(j, "drawing_name", json_object_new_string(label));
246 call(wmAPI, "deactivate_surface", json_object_to_json_string(j));
252 int AFBClient::endDraw(const char *label)
255 json_object *j = json_object_new_object();
256 json_object_object_add(j, "drawing_name", json_object_new_string(label));
257 call(wmAPI, "enddraw", json_object_to_json_string(j));
264 void AFBClient::call(const char *api, const char *verb, const char *object)
273 /* allocates an id for the request */
274 rc = asprintf(&key, "%d:%s/%s", ++num, api, verb);
276 /* send the request */
277 rc = afb_wsj1_call_s(wsj1, api, verb, object, onReply, key);
279 fprintf(stderr, "calling %s/%s(%s) failed: %m\n", api, verb, object);
284 void AFBClient::set_event_handler(enum EventType at, std::function<void(char const *)> func) {