Skip to content

Commit

Permalink
lib: ws add /current-services/apps/ route
Browse files Browse the repository at this point in the history
  • Loading branch information
alanlivio committed May 3, 2021
1 parent 66a91f1 commit d98edcb
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 20 deletions.
119 changes: 99 additions & 20 deletions lib/WebServices.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
#include <WebServices.h>
#include <Formatter.h>
#include <Document.h>
#include <Media.h>
#include <Document.h>
#include <gio/gio.h>
#include <json/json.h>
#include <algorithm>
#include <iostream>

// routes
#define WS_ROURTE_LOC "/location"
#define WS_ROURTE_RPLAYER "/remote-mediaplayer"
#define WS_ROURTE_APPS "/current-service/apps/"
#define WS_PORT 44642
#define SSDP_UUID "uuid:b16f8e7e-8050-11eb-8036-00155dfe4f40"
#define SSDP_DEVICE "upnp:rootdevice"
#define SSDP_NAME "TeleMidia GingaCCWebServices"
#define SSDP_USN "urn:schemas-sbtvd-org:service:GingaCCWebServices:1"

#define WS_LOG_REQUEST(msg) \
#define WS_ADD_ROUTE(ws, r, f) \
G_STMT_START \
{ \
soup_server_add_handler (ws, r, f, this, nullptr); \
} \
G_STMT_END

#define TRACE_RQ_HEADERS(msg) \
G_STMT_START \
{ \
SoupMessageHeadersIter it; \
Expand Down Expand Up @@ -46,15 +56,15 @@ WebServices::~WebServices ()
bool
WebServices::machMediaThenSetPlayerRemote (PlayerRemoteData &data)
{
// if (xpathisuri (data.location) || data.supportedFormats.empty ())
// return false;
if (!getCurrentDocument ())
return false;

bool found = false;
auto mrts = _formatter->getDocument ()->getMediasRemote ();
if (mrts->empty ())
return false;

// match media deviceType then set remotePlayerBaseURL
bool found = false;
auto it = find_if (mrts->begin (), mrts->end (), [data] (Media *m) {
return (m->getProperty ("device") == data.deviceType);
});
Expand Down Expand Up @@ -85,6 +95,12 @@ WebServices::isStarted ()
return _started;
}

Document *
WebServices::getCurrentDocument ()
{
return _formatter->getDocument ();
}

static void
ws_null_callback (SoupServer *server, SoupMessage *msg, const char *path,
GHashTable *query, SoupClientContext *client,
Expand Down Expand Up @@ -130,8 +146,9 @@ ws_remoteplayer_callback (SoupServer *server, SoupMessage *msg,
Json::CharReader *reader = builder.newCharReader ();
string errors;
WebServices *ws = (WebServices *) user_data;
bool status;

WS_LOG_REQUEST (msg);
TRACE_RQ_HEADERS (msg);

if (!reader->parse (msg->request_body->data,
msg->request_body->data + msg->request_body->length,
Expand All @@ -147,10 +164,79 @@ ws_remoteplayer_callback (SoupServer *server, SoupMessage *msg,
list<string> recognizableEvents;
for (const auto &item : root["recognizableEvents"])
recognizableEvents.push_back (item.asString ());
if (ws->machMediaThenSetPlayerRemote (pdata))
soup_message_set_status (msg, SOUP_STATUS_OK);
status = ws->machMediaThenSetPlayerRemote (pdata);
soup_message_set_status (msg,
status ? SOUP_STATUS_OK : SOUP_STATUS_NOT_FOUND);
}

static void
ws_apps_callback (SoupServer *server, SoupMessage *msg, const char *path,
GHashTable *query, SoupClientContext *client,
gpointer user_data)
{
Json::Value root;
Json::CharReaderBuilder builder;
Json::CharReader *reader = builder.newCharReader ();
string errors;
WebServices *ws = (WebServices *) user_data;
bool status = false;
string action, interface, value;
Object *node;
Event *evt;
const char *target = path + strlen (WS_ROURTE_APPS);
gchar **params = g_strsplit (target, "/", 3);
const char *appId = params[0];
const char *docId = params[1];
const char *nodeId = params[2];

if (!ws->getCurrentDocument () || !strlen (appId) || !strlen (docId)
|| !strlen (nodeId))
goto fail;

TRACE ("request %s: app=%s, docId=%s nodeId=%s", WS_ROURTE_APPS, appId,
docId, nodeId);
TRACE_RQ_HEADERS (msg);

if (!reader->parse (msg->request_body->data,
msg->request_body->data + msg->request_body->length,
&root, &errors))
{
WARNING ("Error parsing request body");
goto fail;
}
action = root["action"].asString ();
interface = root["interface"].asString ();
value = root["value"].asString ();

node = ws->getCurrentDocument ()->getObjectById (nodeId);
g_assert_nonnull (node);

if (xstrcasecmp (action, "select") == 0)
{
evt = node->getSelectionEvent (value);
ws->getCurrentDocument ()->evalAction (evt, Event::START);
ws->getCurrentDocument ()->evalAction (evt, Event::STOP);
}
else if (xstrcasecmp (action, "lookAt") == 0)
{
evt = node->getLookAtEvent ("@lambda");
ws->getCurrentDocument ()->evalAction (evt, Event::START);
}
else if (xstrcasecmp (action, "lookAway") == 0)
{
evt = node->getLookAtEvent ("@lambda");
ws->getCurrentDocument ()->evalAction (evt, Event::STOP);
}
else
soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
{
goto fail;
}

soup_message_set_status (msg, SOUP_STATUS_OK);

fail:
g_strfreev (params);
soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
}

bool
Expand Down Expand Up @@ -193,18 +279,11 @@ WebServices::start ()
goto fail;
}

// add route /location ()
soup_server_add_handler (_ws, "/location", ws_loc_callback, this,
nullptr);

// add route /remoteplayer ()
soup_server_add_handler (_ws, "/remote-mediaplayer",
ws_remoteplayer_callback, this, nullptr);

// add route NULL
soup_server_add_handler (_ws, nullptr, ws_null_callback, this, nullptr);
WS_ADD_ROUTE (_ws, WS_ROURTE_LOC, ws_loc_callback);
WS_ADD_ROUTE (_ws, WS_ROURTE_RPLAYER, ws_remoteplayer_callback);
WS_ADD_ROUTE (_ws, WS_ROURTE_APPS, ws_apps_callback);
WS_ADD_ROUTE (_ws, nullptr, ws_null_callback);

// all done
_started = true;
return true;
fail:
Expand Down
2 changes: 2 additions & 0 deletions lib/WebServices.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ along with Ginga. If not, see <https://www.gnu.org/licenses/>. */

GINGA_NAMESPACE_BEGIN
class Formatter;
class Document;
class Media;

/**
Expand All @@ -50,6 +51,7 @@ class WebServices
bool isStarted ();
const char *_host_addr;
bool machMediaThenSetPlayerRemote (PlayerRemoteData &);
Document *getCurrentDocument ();

private:
Formatter *_formatter;
Expand Down

0 comments on commit d98edcb

Please sign in to comment.