Add sound manager initial source code
[staging/soundmanager.git] / sample / mediaplayer / app / main.cpp
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  * Copyright (C) 2017 Toyota Motor Corporation
4  *
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
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"
29
30 #ifdef HAVE_LIBHOMESCREEN
31 #include <libhomescreen.hpp>
32 #endif
33
34 #include "playlistwithmetadata.h"
35
36 LibSMWrapper* smw;
37 static int mysourceID = 0;
38 static bool firsttime = true;
39 QObject *root;
40
41 static void onRep(struct json_object* reply_contents);
42 static void onEv(const std::string& event, struct json_object* event_contents);
43
44 int main(int argc, char *argv[])
45 {
46 #ifdef HAVE_LIBHOMESCREEN
47     LibHomeScreen libHomeScreen;
48
49     if (!libHomeScreen.renderAppToAreaAllowed(0, 1)) {
50         qWarning() << "renderAppToAreaAllowed is denied";
51         return -1;
52     }
53 #endif
54
55     QGuiApplication app(argc, argv);
56
57     QQuickStyle::setStyle("AGL");
58
59     qmlRegisterType<PlaylistWithMetadata>("MediaPlayer", 1, 0, "PlaylistWithMetadata");
60
61     QQmlApplicationEngine engine;
62     QQmlContext *context = engine.rootContext();
63
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();
69     parser.process(app);
70     QStringList positionalArguments = parser.positionalArguments();
71
72     if (positionalArguments.length() == 2) {
73         int port = positionalArguments.takeFirst().toInt();
74         QString secret = positionalArguments.takeFirst();
75         QUrl bindingAddress;
76         bindingAddress.setScheme(QStringLiteral("ws"));
77         bindingAddress.setHost(QStringLiteral("localhost"));
78         bindingAddress.setPort(port);
79         bindingAddress.setPath(QStringLiteral("/api"));
80         QUrlQuery query;
81         query.addQueryItem(QStringLiteral("token"), secret);
82         bindingAddress.setQuery(query);
83         context->setContextProperty(QStringLiteral("bindingAddress"), bindingAddress);
84
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"));
90         smw->run_eventloop();
91         engine.rootContext()->setContextProperty("smw",smw);
92     }
93
94     engine.load(QUrl(QStringLiteral("qrc:/MediaPlayer.qml")));
95
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)));
101         
102     return app.exec();
103 }
104
105 static void onRep(struct json_object* reply_contents)
106 {
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();
112
113     smw->emit_reply(jobj);
114     json_object_put(reply_contents);
115 }
116
117 static void onEv(const std::string& event, struct json_object* event_contents)
118 {
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());
122
123     if(firsttime){
124         qDebug("check to return acknowledge to SM");
125         if(!event_name.contains("asyncSetSourceState", Qt::CaseSensitive)){
126             return;
127         }
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;
131         qDebug() << str;
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");
137             return;
138         }
139
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);
144
145         if(event_sourceID != mysourceID){
146             qDebug("sourceID is not designated to me");
147             return;
148         }
149
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);
156         /* to here */
157         firsttime = false;
158     }
159     
160     QJsonParseError error;
161     QJsonDocument jdoc = QJsonDocument::fromJson(str.toUtf8(), &error);
162     const QJsonObject jobj = jdoc.object();
163     smw->emit_event(event_name, jobj);
164
165     json_object_put(event_contents);
166 }