Added new DIAL app for Oregano
Added callbacks to populate Cast servicedata and activity-status
Implement servicedata callback to publish Basil URL
Change-Id: I69835e93290ff196fbfaeb71774e0326d62b05d5
diff --git a/src/server/dial_options.h b/src/server/dial_options.h
index 6c24a1b..3c32e29 100644
--- a/src/server/dial_options.h
+++ b/src/server/dial_options.h
@@ -38,6 +38,10 @@
#define UUID_OPTION_LONG "--uuid-name"
#define UUID_DESCRIPTION "UUID of the device"
+#define UI_TYPE_OPTION "-I"
+#define UI_TYPE_OPTION_LONG "--ui-type"
+#define UI_TYPE_DESCRIPTION "UI type"
+
struct dial_options
{
const char * pOption;
@@ -61,6 +65,11 @@
UUID_OPTION,
UUID_OPTION_LONG,
UUID_DESCRIPTION
+ },
+ {
+ UI_TYPE_OPTION,
+ UI_TYPE_OPTION_LONG,
+ UI_TYPE_DESCRIPTION
}
};
diff --git a/src/server/dial_server.c b/src/server/dial_server.c
index b60da30..ac7c210 100644
--- a/src/server/dial_server.c
+++ b/src/server/dial_server.c
@@ -166,12 +166,36 @@
"<service xmlns=\"urn:dial-multiscreen-org:schemas:dial\">\r\n"
" <name>%s</name>\r\n"
" <options allowStop=\"%s\"/>\r\n"
- " <state>%s</state>\r\n"
- "%s"
- "</service>\r\n", app->name, canStop ? "true":"false",
- app->state ? "running" : "stopped",
- app->state == kDIALStatusStopped ?
- "" : " <link rel=\"run\" href=\"run\"/>\r\n" );
+ " <state>%s</state>\r\n",
+ app->name, canStop ? "true":"false",
+ app->state ? "running" : "stopped");
+ if (app->state != kDIALStatusStopped) {
+ mg_printf(conn,
+ " <link rel=\"run\" href=\"run\"/>\r\n");
+ }
+ if (app->callbacks.service_data_cb != NULL) {
+ struct CastServiceData serviceData = app->callbacks.service_data_cb(ds, app_name, app->run_id, app->callback_data);
+ mg_printf(conn,
+ " <servicedata xmlns=\"urn:chrome.google.com:cast\">\r\n"
+ " <connectionSvcURL>http://%s:%d%s</connectionSvcURL>\r\n"
+ " <protocols>\r\n"
+ " <protocol>%s</protocol>\r\n"
+ " </protocols>\r\n"
+ " </servicedata>\r\n",
+ serviceData.connection_svc_host,
+ serviceData.connection_svc_port,
+ serviceData.connection_svc_path,
+ serviceData.protocol);
+ }
+ if (app->callbacks.activity_status_cb != NULL) {
+ struct CastActivityStatus activityStatus = app->callbacks.activity_status_cb(ds, app_name, app->run_id, app->callback_data);
+ mg_printf(conn,
+ " <activity-status xmlns=\"urn:chrome.google.com:cast\">\r\n"
+ " <description>%s</description>\r\n"
+ " </activity-status>\r\n"
+ " </servicedata>\r\n", activityStatus.description);
+ }
+ mg_printf(conn, "</service>\r\n");
}
ds_unlock(ds);
}
diff --git a/src/server/dial_server.h b/src/server/dial_server.h
index fa309ad..dee72d3 100644
--- a/src/server/dial_server.h
+++ b/src/server/dial_server.h
@@ -42,6 +42,23 @@
#define DIAL_MAX_PAYLOAD (4096)
/*
+ * Cast service data
+ */
+struct CastServiceData {
+ const char *connection_svc_host;
+ int connection_svc_port;
+ const char *connection_svc_path;
+ const char *protocol;
+};
+
+/*
+ * Cast activity status
+ */
+struct CastActivityStatus {
+ const char *description;
+};
+
+/*
* Opaque DIAL server handle
*/
struct DIALServer_;
@@ -69,6 +86,17 @@
typedef DIALStatus (*DIAL_app_status_cb)(DIALServer *ds, const char *app_name,
DIAL_run_t run_id, int* pCanStop,
void *callback_data);
+/*
+ * Cast service data callback
+ */
+typedef struct CastServiceData (*CAST_app_service_data_cb)(DIALServer *ds, const char *app_name,
+ DIAL_run_t run_id, void *callback_data);
+
+/*
+ * Cast service data callback
+ */
+typedef struct CastActivityStatus (*CAST_app_activity_status_cb)(DIALServer *ds, const char *app_name,
+ DIAL_run_t run_id, void *callback_data);
/*
* DIAL callbacks
@@ -77,6 +105,8 @@
DIAL_app_start_cb start_cb;
DIAL_app_stop_cb stop_cb;
DIAL_app_status_cb status_cb;
+ CAST_app_service_data_cb service_data_cb;
+ CAST_app_activity_status_cb activity_status_cb;
};
/*
diff --git a/src/server/main.c b/src/server/main.c
index 57bc0eb..7eabcdc 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -46,6 +46,7 @@
static char spFriendlyName[BUFSIZE];
static char spModelName[BUFSIZE];
static char spUuid[BUFSIZE];
+static char spUiType[BUFSIZE];
static int gDialPort;
static char *spAppNetflix = "netflix"; // name of the netflix executable
@@ -57,9 +58,14 @@
static char *spAppFiberTV = "miniclient";
static char *spAppFiberTVMatch = NULL;
+static char *spAppOregano = "content_shell";
+static char *spAppOreganoMatch = "fiber.google.com/oregano";
+
// Adding 20 bytes for prepended source_type for Netflix
static char sQueryParam[DIAL_MAX_PAYLOAD+20];
+static const char *spIpAddress;
+
static int doesMatch( char* pzExp, char* pzStr)
{
regex_t exp;
@@ -365,7 +371,46 @@
}
}
-void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid);
+static DIALStatus oregano_start(DIALServer *ds, const char *appname,
+ const char *args, size_t arglen,
+ DIAL_run_t *run_id, void *callback_data) {
+ fprintf(stderr, "** LAUNCH GoogleFiberTV **\n");
+ // TODO(pbaldwin): Add ability to start Oregano when not already running
+ pid_t pid;
+ if ((pid = isAppRunning( spAppOregano, spAppOreganoMatch ))) {
+ *run_id = (void *)(long)pid;
+ return kDIALStatusRunning;
+ } else {
+ return kDIALStatusStopped;
+ }
+}
+
+static DIALStatus oregano_status(DIALServer *ds, const char *appname,
+ DIAL_run_t run_id, int *pCanStop, void *callback_data) {
+ *pCanStop = 1;
+ return isAppRunning( spAppOregano, spAppOreganoMatch ) ? kDIALStatusRunning : kDIALStatusStopped;
+}
+
+static struct CastServiceData oregano_service_data(DIALServer *ds, const char *appname,
+ DIAL_run_t run_id, void *callback_data) {
+ struct CastServiceData serviceData;
+ serviceData.connection_svc_host = spIpAddress;
+ serviceData.connection_svc_port = 5153;
+ serviceData.connection_svc_path = "/connections";
+ serviceData.protocol = "marjoram";
+ return serviceData;
+}
+
+static void oregano_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id,
+ void *callback_data) {
+ fprintf(stderr, "** KILL GoogleFiberTV **\n");
+ pid_t pid;
+ if ((pid = isAppRunning( spAppOregano, spAppOreganoMatch ))) {
+ kill(pid, SIGTERM);
+ }
+}
+
+void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid, const char **ppIpAddress);
static void printUsage()
{
@@ -392,16 +437,21 @@
{
DIALServer *ds;
ds = DIAL_start();
- struct DIALAppCallbacks cb_nf = {netflix_start, netflix_stop, netflix_status};
- struct DIALAppCallbacks cb_yt = {youtube_start, youtube_stop, youtube_status};
- struct DIALAppCallbacks cb_ft = {fibertv_start, fibertv_stop, fibertv_status};
+ struct DIALAppCallbacks cb_nf = {netflix_start, netflix_stop, netflix_status, NULL, NULL};
+ struct DIALAppCallbacks cb_yt = {youtube_start, youtube_stop, youtube_status, NULL, NULL};
+ struct DIALAppCallbacks cb_ft = {fibertv_start, fibertv_stop, fibertv_status, NULL, NULL};
+ struct DIALAppCallbacks cb_or = {oregano_start, oregano_stop, oregano_status, oregano_service_data, NULL};
DIAL_register_app(ds, "Netflix", &cb_nf, NULL);
DIAL_register_app(ds, "YouTube", &cb_yt, NULL);
- DIAL_register_app(ds, "FiberTV", &cb_ft, NULL);
+ if (strcmp(spUiType, "oregano") == 0) {
+ DIAL_register_app(ds, "GoogleFiberTV", &cb_or, NULL);
+ } else {
+ DIAL_register_app(ds, "FiberTV", &cb_ft, NULL);
+ }
gDialPort = DIAL_get_port(ds);
fprintf(stderr, "launcher listening on gDialPort %d\n", gDialPort);
- run_ssdp(gDialPort, spFriendlyName, spModelName, spUuid);
+ run_ssdp(gDialPort, spFriendlyName, spModelName, spUuid, &spIpAddress);
DIAL_stop(ds);
}
@@ -419,6 +469,9 @@
case 2: // UUID
setValue( pOption, spUuid );
break;
+ case 3: // UI type
+ setValue( pOption, spUiType );
+ break;
default:
// Should not get here
fprintf( stderr, "Option %d not valid\n", index);
diff --git a/src/server/quick_ssdp.c b/src/server/quick_ssdp.c
index 9cef629..a2da683 100644
--- a/src/server/quick_ssdp.c
+++ b/src/server/quick_ssdp.c
@@ -205,7 +205,7 @@
}
}
-void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid) {
+void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid, const char **ppIpAddress) {
struct sockaddr sa;
socklen_t len = sizeof(sa);
@@ -230,6 +230,7 @@
dial_port = port;
get_local_address();
+ *ppIpAddress = ip_addr;
ctx = mg_start(&request_handler, NULL, SSDP_PORT);
if (mg_get_listen_addr(ctx, &sa, &len)) {