2 * Copyright (C) 2016 The Qt Company Ltd.
3 * Copyright (C) 2017 Toyota Motor Corporation
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <QtCore/QCommandLineParser>
19 #include <QtCore/QDebug>
20 #include <QtCore/QDir>
21 #include <QtCore/QStandardPaths>
22 #include <QtCore/QUrlQuery>
23 #include <QtGui/QGuiApplication>
24 #include <QtQml/QQmlApplicationEngine>
25 #include <QtQml/QQmlContext>
26 #include <QtQml/qqml.h>
27 #include <QtQuickControls2/QQuickStyle>
28 #include "libsmwrapper.h"
30 #ifdef HAVE_LIBHOMESCREEN
31 #include <libhomescreen.hpp>
34 #include "playlistwithmetadata.h"
37 static int mysourceID = 0;
38 static bool firsttime = true;
41 static void onRep(struct json_object* reply_contents);
42 static void onEv(const std::string& event, struct json_object* event_contents);
44 int main(int argc, char *argv[])
46 #ifdef HAVE_LIBHOMESCREEN
47 LibHomeScreen libHomeScreen;
49 if (!libHomeScreen.renderAppToAreaAllowed(0, 1)) {
50 qWarning() << "renderAppToAreaAllowed is denied";
55 QGuiApplication app(argc, argv);
57 QQuickStyle::setStyle("AGL");
59 qmlRegisterType<PlaylistWithMetadata>("MediaPlayer", 1, 0, "PlaylistWithMetadata");
61 QQmlApplicationEngine engine;
62 QQmlContext *context = engine.rootContext();
64 QCommandLineParser parser;
65 parser.addPositionalArgument("port", app.translate("main", "port for binding"));
66 parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
67 parser.addHelpOption();
68 parser.addVersionOption();
70 QStringList positionalArguments = parser.positionalArguments();
72 if (positionalArguments.length() == 2) {
73 int port = positionalArguments.takeFirst().toInt();
74 QString secret = positionalArguments.takeFirst();
76 bindingAddress.setScheme(QStringLiteral("ws"));
77 bindingAddress.setHost(QStringLiteral("localhost"));
78 bindingAddress.setPort(port);
79 bindingAddress.setPath(QStringLiteral("/api"));
81 query.addQueryItem(QStringLiteral("token"), secret);
82 bindingAddress.setQuery(query);
83 context->setContextProperty(QStringLiteral("bindingAddress"), bindingAddress);
85 // prepare to use soundmangaer
86 smw = new LibSMWrapper(port, secret);
87 smw->wrapper_registerCallback(onEv, onRep);
88 smw->subscribe(QString("asyncSetSourceState"));
89 smw->subscribe(QString("asyncConnect"));
91 engine.rootContext()->setContextProperty("smw",smw);
94 engine.load(QUrl(QStringLiteral("qrc:/MediaPlayer.qml")));
96 root = engine.rootObjects().first();
97 QObject::connect(smw, SIGNAL(smEvent(QVariant, QVariant)),
98 root, SLOT(slotEvent(QVariant, QVariant)));
99 QObject::connect(smw, SIGNAL(smReply(QVariant)),
100 root, SLOT(slotReply(QVariant)));
105 static void onRep(struct json_object* reply_contents)
107 qDebug("%s is called", __FUNCTION__);
108 QString str = QString(json_object_get_string(reply_contents));
109 QJsonParseError error;
110 QJsonDocument jdoc = QJsonDocument::fromJson(str.toUtf8(), &error);
111 QJsonObject jobj = jdoc.object();
113 smw->emit_reply(jobj);
114 json_object_put(reply_contents);
117 static void onEv(const std::string& event, struct json_object* event_contents)
119 qDebug("%s is called", __FUNCTION__);
120 QString str = QString(json_object_get_string(event_contents));
121 const QString event_name = QString(event.c_str());
124 qDebug("check to return acknowledge to SM");
125 if(!event_name.contains("asyncSetSourceState", Qt::CaseSensitive)){
128 /* this is temporary fix because QML doesn't catch signal if application is on background first*/
129 qDebug("return acknowledge to SM");
130 struct json_object *content_data, *content_handle, *content_sourceID;
132 json_object_object_get_ex(event_contents,"data", &content_data);
133 json_bool has_handle = json_object_object_get_ex(content_data,"handle",&content_handle);
134 json_bool has_sourceID = json_object_object_get_ex(content_data,"sourceID",&content_sourceID);
135 if(!has_handle || !has_sourceID){
136 qDebug("doesn't have sourceID/handle");
140 int event_sourceID = json_object_get_int(content_sourceID);
141 /* QML has sourceID */
142 mysourceID = root->property("sourceID").toInt();
143 qDebug("my sourceID is %d", mysourceID);
145 if(event_sourceID != mysourceID){
146 qDebug("sourceID is not designated to me");
150 /* Following code is mediaplayer only because mediaplayer doen't react in background first if it is on background*/
151 struct json_object* ret_obj = json_object_new_object();
152 json_object_object_add(ret_obj, "handle", content_handle);
153 json_object_object_add(ret_obj, "error", json_object_new_int(0));
154 QString ret = QString(json_object_get_string(ret_obj));
155 smw->call(QString("ackSetSourceState"), ret);
160 QJsonParseError error;
161 QJsonDocument jdoc = QJsonDocument::fromJson(str.toUtf8(), &error);
162 const QJsonObject jobj = jdoc.object();
163 smw->emit_event(event_name, jobj);
165 json_object_put(event_contents);