TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicidentifysongrequest.cpp
Go to the documentation of this file.
3 
4 #include "qsync/qsyncutils.h"
5 
6 #include <QFile>
7 
8 static constexpr const char *OS_ACRCLOUD_URL = "acrcloud";
9 static constexpr const char *QUERY_URL = "VzBxZCtBUDBKK1R6aHNiTGxMdy84SzlIUVA5a3cvbjdKQ1ZIVGdYRThBS0hZMTlZSnhRQ0Y5N0lZdi9QQ3VveVEyVDdXbll3ZUZvPQ==";
10 
12  : MusicAbstractNetwork(parent)
13 {
14 
15 }
16 
18 {
19  TTKSemaphoreLoop loop;
20  connect(this, SIGNAL(finished()), &loop, SLOT(quit()));
21 
23  connect(d, SIGNAL(downLoadRawDataChanged(QByteArray)), SLOT(downLoadFinished(QByteArray)));
25  loop.exec();
26 
27  return !m_accessKey.isEmpty() && !m_accessSecret.isEmpty();
28 }
29 
31 {
32  const QString &boundary = "----";
33  const QString &start = "--" + boundary;
34  const QString &end = "\r\n--" + boundary + "--\r\n";
35  const QString &contentType = "multipart/form-data; boundary=" + boundary;
36 
37  const QString &method = "POST";
38  const QString &endpoint = "/v1/identify";
39  const QString &type = "fingerprint";
40  const QString &version = "1";
41  const QString &timeStamp = QString::number(TTKDateTime::currentTimestamp());
42 
43  const QString &sign = method + "\n" + endpoint + "\n" + m_accessKey + "\n" + type + "\n" + version + "\n" + timeStamp;
44  QByteArray body = TTK::Algorithm::hmacSha1(sign.toUtf8(), m_accessSecret.toUtf8()).toBase64();
45 
46  QString value;
47  value += start + "\r\nContent-Disposition: form-data; name=\"access_key\"\r\n\r\n" + m_accessKey + "\r\n";
48  value += start + "\r\nContent-Disposition: form-data; name=\"data_type\"\r\n\r\n" + type + "\r\n";
49  value += start + "\r\nContent-Disposition: form-data; name=\"timestamp\"\r\n\r\n" + timeStamp + "\r\n";
50  value += start + "\r\nContent-Disposition: form-data; name=\"signature_version\"\r\n\r\n" + version + "\r\n";
51  value += start + "\r\nContent-Disposition: form-data; name=\"signature\"\r\n\r\n" + body + "\r\n";
52 
53  QFile file(path);
54  if(!file.open(QIODevice::ReadOnly))
55  {
56  TTK_ERROR_STREAM("Load input audio wav file error");
57  return;
58  }
59 
60  value += start + "\r\nContent-Disposition: form-data; name=\"sample_bytes\"\r\n\r\n" + QString::number(file.size()) + "\r\n";
61  value += start + "\r\nContent-Disposition: form-data; name=\"sample\"; filename=\"" + file.fileName() + "\"\r\n";
62  value += "Content-Type: application/octet-stream\r\n\r\n";
63 
64  body.clear();
65  body.append(value.toUtf8());
66  body.append(file.readAll());
67  body.append(end.toUtf8());
68  file.close();
69 
70  QNetworkRequest request;
71  request.setUrl(TTK::Algorithm::mdII(QUERY_URL, false));
72  TTK::setSslConfiguration(&request);
73  TTK::makeContentTypeHeader(&request, contentType.toUtf8());
74 
75  m_reply = m_manager.post(request, body);
76  connect(m_reply, SIGNAL(finished()), SLOT(downLoadFinished()));
77  QtNetworkErrorConnect(m_reply, this, replyError, TTK_SLOT);
78 }
79 
81 {
83  m_items.clear();
84 
85  if(m_reply && m_reply->error() == QNetworkReply::NoError)
86  {
87  QJson::Parser json;
88  bool ok = false;
89  const QVariant &data = json.parse(m_reply->readAll(), &ok);
90  if(ok)
91  {
92  QVariantMap value = data.toMap();
93  if(value.contains("metadata"))
94  {
95  value = value["metadata"].toMap();
96 
97  const QVariantList &datas = value["music"].toList();
98  for(const QVariant &var : qAsConst(datas))
99  {
100  value = var.toMap();
102 
104  song.m_songName = value["title"].toString();
105  for(const QVariant &artists : value["artists"].toList())
106  {
107  value = artists.toMap();
108  song.m_artistName = TTK::String::charactersReplace(value["name"].toString());
109  break;
110  }
111 
112  m_items << song;
113  break;
114  }
115  }
116  else
117  {
118  TTK_INFO_STREAM("No result in acrcloud server");
119  }
120  }
121  }
122 
123  Q_EMIT downLoadDataChanged({});
124  deleteAll();
125 }
126 
127 void MusicIdentifySongRequest::downLoadFinished(const QByteArray &bytes)
128 {
129  if(bytes.isEmpty())
130  {
131  TTK_ERROR_STREAM("Input byte data is empty");
132  }
133  else
134  {
135  QJson::Parser json;
136  bool ok = false;
137  const QVariant &data = json.parse(bytes, &ok);
138  if(ok)
139  {
140  const QVariantMap &value = data.toMap();
141  if(QDateTime::fromString(value["time"].toString(), TTK_DATE_TIMEZ_FORMAT) > QDateTime::currentDateTime())
142  {
143  m_accessKey = value["key"].toString();
144  m_accessSecret = value["secret"].toString();
145  }
146  }
147  }
148 
149  Q_EMIT finished();
150 }
TTK_MODULE_EXPORT QString charactersReplace(const QString &value)
#define TTK_NETWORK_QUERY_CHECK(VALUE)
virtual void deleteAll()
void downLoadDataChanged(const QString &bytes)
QNetworkReply * m_reply
void downLoadRawDataChanged(const QByteArray &bytes)
#define TTK_DATE_TIMEZ_FORMAT
Definition: ttkglobal.h:234
virtual void downLoadFinished() overridefinal
TTK_MODULE_EXPORT void setSslConfiguration(QNetworkRequest *request, QSslSocket::PeerVerifyMode mode=QSslSocket::VerifyNone)
TTK_MODULE_EXPORT QByteArray hmacSha1(const QByteArray &data, const QByteArray &key)
int exec(ProcessEventsFlags flags=AllEvents)
virtual void downLoadFinished()
The class of the song identify data item.
#define qAsConst
Definition: ttkqtglobal.h:53
MusicSongIdentifyDataList m_items
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:67
void startToRequest(const QString &path)
The class of the data source download request.
QNetworkAccessManager m_manager
virtual void replyError(QNetworkReply::NetworkError error) override
QVariant parse(QIODevice *io, bool *ok=0)
Read JSON string from the I/O Device and converts it to a QVariant object.
Definition: parser.cpp:69
static constexpr const char * QUERY_URL
#define TTK_SLOT
Definition: ttkqtglobal.h:165
The class of the abstract network.
static constexpr const char * OS_ACRCLOUD_URL
void startToRequest(const QString &url)
MusicIdentifySongRequest(QObject *parent=nullptr)
static qint64 currentTimestamp()
Definition: ttktime.cpp:249
TTK_MODULE_EXPORT void makeContentTypeHeader(QNetworkRequest *request, const QByteArray &data={})
TTK_MODULE_EXPORT QString toString(Record type)
Main class used to convert JSON data to QVariant objects.
Definition: parser.h:40
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:69
The class of the semaphore event loop.
TTK_MODULE_EXPORT QString mdII(const QString &data, bool encode)
static QString makeDataBucketUrl()
Definition: qsyncutils.cpp:90
#define QtNetworkErrorConnect(p, q, f, s)
Network error connect.
Definition: ttkqtcompat.h:59