TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
qdlnaclient.cpp
Go to the documentation of this file.
1 #include "qdlnaclient.h"
2 #include "qdlnaxml.h"
3 
4 #include <QMap>
5 #include <unistd.h>
6 #include <QStringList>
7 
8 static constexpr const char *AVTRANSPORT = "avtransport";
9 
10 static const QString XML_HEAD = "<?xml version=\"1.0\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n<SOAP-ENV:Body>\n";
11 static const QString XML_FOOT = "</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\n";
12 static const QStringList FRIENS_NAMES = {"friendlyname", "friendlyName", "FriendlyName", "FriendlyName"};
13 static const QStringList AVT_NAMES = {"avtransport", "AVTransport"};
14 
18 class QDlnaClientPrivate : public TTKPrivate<QDlnaClient>
19 {
20 public:
23 
24  void initialize(const QString &data);
25  bool connectServer();
26 
28 
31  QString m_smp, m_controlURL;
32  QString m_friendlyName;
33  QMap<QString, QDlnaService> m_services;
34 
35 };
36 
38  : m_isConnected(false),
39  m_xml(new QDlnaXml)
40 {
41 
42 }
43 
45 {
46  delete m_xml;
47 }
48 
49 void QDlnaClientPrivate::initialize(const QString &data)
50 {
51  const QStringList &list = data.split("\r\n");
52  for(QString str : qAsConst(list))
53  {
54  QStringList data_list;
55  if(str.contains("LOCATION:"))
56  {
57  data_list = str.remove("LOCATION: http://").split(":");
58  }
59  else if(str.contains("Location:"))
60  {
61  data_list = str.remove("Location: http://").split(":");
62  }
63  else if(str.contains("location:"))
64  {
65  data_list = str.remove("location: http://").split(":");
66  }
67 
68  if(data_list.count() >= 2)
69  {
70  m_serverIP = data_list[0];
71  const QStringList &info_list = data_list[1].split(TTK_SEPARATOR);
72 
73  if(info_list.count() >= 2)
74  {
75  m_serverPort = info_list[0];
76  m_smp = info_list[1];
77  }
78  }
79  }
80 }
81 
83 {
84  const QString &request = QDlnaHelper::MakeRequest("GET", m_smp, 0, {}, m_serverIP, m_serverPort);
85  const QString &response = QDlnaHelper::makeSocketGetReply(m_serverIP, m_serverPort, request);
86  TTK_INFO_STREAM(m_serverIP << m_serverPort << m_smp << response);
87  const int code = QDlnaHelper::GetResponseCode(response);
88  if(code != 200)
89  {
90  return false;
91  }
92 
93  const QString &body = QDlnaHelper::removeHttpHeader(response);
94  if(!m_xml->fromString(m_xml->tagNameToLower(body)))
95  {
96  return false;
97  }
98  //
99  for(const QString &name : qAsConst(FRIENS_NAMES))
100  {
102  if(!m_friendlyName.isEmpty())
103  {
104  break;
105  }
106  }
107  if(m_friendlyName.isEmpty())
108  {
109  return false;
110  }
111  //
112  for(const QString &name : qAsConst(AVT_NAMES))
113  {
114  QDlnaService server = m_xml->readServiceTag(name, "server");
115  if(!server.isEmpty())
116  {
117  m_services.insert(AVTRANSPORT, server);
118  break;
119  }
120  }
121  //
122  for(const QString &name : qAsConst(AVT_NAMES))
123  {
124  QDlnaService server = m_xml->readServiceTag(name, "service");
125  if(!server.isEmpty())
126  {
127  m_services.insert(AVTRANSPORT, server);
128  break;
129  }
130  }
131  //
132  for(auto it = m_services.begin(); it != m_services.end(); ++it)
133  {
134  if(it.key().contains(AVTRANSPORT))
135  {
136  m_controlURL = it.value().m_controlURL;
137  m_isConnected = true;
138  return true;
139  }
140  }
141  return false;
142 }
143 
144 
145 
146 QDlnaClient::QDlnaClient(const QString &data)
147 {
150  d->initialize(data);
151 }
152 
154 {
156  return d->m_serverIP;
157 }
158 
160 {
162  return d->m_friendlyName;
163 }
164 
166 {
168  return d->connectServer();
169 }
170 
172 {
174  return d->m_isConnected;
175 }
176 
177 QString QDlnaClient::tryToPlayFile(const QString &url)
178 {
179  uploadFileToPlay(url);
180  const QString &playState = startPlay(0);
181  return playState;
182 }
183 
184 QString QDlnaClient::uploadFileToPlay(const QString &url)
185 {
187  //Later we will send a message to the DLNA server to start the file playing
188  QString play_url = url;
189  QString body = XML_HEAD;
190  body += "<u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\n";
191  body += "<InstanceID>0</InstanceID>\n";
192  body += "<CurrentURI>" + play_url.replace(" ", "%20") + "</CurrentURI>\n";
193  body += "</u:SetAVTransportURI>\n";
194  body += XML_FOOT + "\n";
195  const QString &request = QDlnaHelper::MakeRequest("POST", d->m_controlURL, body.length(), "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI", d->m_serverIP,d->m_serverPort) + body;
196  TTK_INFO_STREAM(request);
197  return QDlnaHelper::makeSocketGetReply(d->m_serverIP, d->m_serverPort, request);
198 }
199 
200 QString QDlnaClient::startPlay(int instance)
201 {
203  //Start playing the new upload film or music track
204  QString body = XML_HEAD;
205  body += "<u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>"+ QString::number(instance) + "</InstanceID><Speed>1</Speed></u:Play>\n";
206  body += XML_FOOT + "\n";
207  const QString &request = QDlnaHelper::MakeRequest("POST", d->m_controlURL, body.length(), "urn:schemas-upnp-org:service:AVTransport:1#Play", d->m_serverIP, d->m_serverPort) + body;
208  return QDlnaHelper::makeSocketGetReply(d->m_serverIP, d->m_serverPort, request);
209 }
210 
211 QString QDlnaClient::stopPlay(int instance)
212 {
214  //Called to stop playing a movie or a music track
215  QString body = XML_HEAD;
216  body += "<u:Stop xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>" + QString::number(instance) + "</InstanceID></u:Stop>\n";
217  body += XML_FOOT + "\n";
218  const QString &request = QDlnaHelper::MakeRequest("POST", d->m_controlURL, body.length(), "urn:schemas-upnp-org:service:AVTransport:1#Stop", d->m_serverIP, d->m_serverPort) + body;
219  return QDlnaHelper::makeSocketGetReply(d->m_serverIP, d->m_serverPort, request);
220 }
221 
222 QString QDlnaClient::pause(int instance)
223 {
225  //Called to pause playing a movie or a music track
226  QString body = XML_HEAD;
227  body += "<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>" + QString::number(instance) + "</InstanceID></u:Pause>\n";
228  body += XML_FOOT + "\n";
229  const QString &request = QDlnaHelper::MakeRequest("POST", d->m_controlURL, body.length(), "urn:schemas-upnp-org:service:AVTransport:1#Pause", d->m_serverIP, d->m_serverPort) + body;
230  return QDlnaHelper::makeSocketGetReply(d->m_serverIP, d->m_serverPort, request);
231 }
232 
234 {
236  //Returns the current position for the track that is playing on the DLNA server
237  const QString &body = XML_HEAD + "<m:GetPositionInfo xmlns:m=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"ui4\">0</InstanceID></m:GetPositionInfo>" + XML_FOOT + "\n";
238  const QString &request = QDlnaHelper::MakeRequest("POST", d->m_controlURL, body.length(), "urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo", d->m_serverIP, d->m_serverPort) + body;
239  return QDlnaHelper::makeSocketGetReply(d->m_serverIP, d->m_serverPort, request);
240 }
241 
242 int QDlnaClient::totalSeconds(const QString &value)
243 {
244  //Convert the time left for the track to play back to seconds
245  const QStringList &data_list = value.split(TTK_DOT);
246  if(data_list.count() >= 2)
247  {
248  const QStringList &info_list = data_list[1].split(":");
249  if(info_list.count() >= 2)
250  {
251  const int mins = info_list[0].toInt();
252  const int secs = info_list[1].toInt();
253  return mins * 60 + secs;
254  }
255  }
256  return 0;
257 }
QString serverName()
QString uploadFileToPlay(const QString &url)
QString stopPlay(int instance)
QString position()
QMap< QString, QDlnaService > m_services
Definition: qdlnaclient.cpp:33
QString MakeRequest(const QString &methord, const QString &url, int length, const QString &soapAction, const QString &ip, const QString &port)
Definition: qdlnahelper.cpp:9
QString pause(int instance)
The class of the dlna client.
Definition: qdlnaclient.h:29
QString removeHttpHeader(const QString &data)
Definition: qdlnahelper.cpp:70
QString tryToPlayFile(const QString &url)
static const QStringList AVT_NAMES
Definition: qdlnaclient.cpp:13
QString makeSocketGetReply(const QString &ip, const QString &port, const QString &data)
Definition: qdlnahelper.cpp:40
QString server()
QString tagNameToLower(const QString &data) const
Definition: qdlnaxml.cpp:56
#define TTK_DOT
Definition: ttkglobal.h:193
The class of the dlna xml.
Definition: qdlnaxml.h:29
bool connect()
QString readTagNameValue(const QString &tagName) const
Definition: qdlnaxml.cpp:75
bool isEmpty() const
Definition: qdlnaservice.h:35
#define qAsConst
Definition: ttkqtglobal.h:53
const char * name
Definition: http_parser.c:458
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:67
static const QString XML_FOOT
Definition: qdlnaclient.cpp:11
int totalSeconds(const QString &value)
#define TTK_SEPARATOR
Definition: ttkglobal.h:195
The class of the dlna service.
Definition: qdlnaservice.h:27
Definition: inftrees.h:24
static const QStringList FRIENS_NAMES
Definition: qdlnaclient.cpp:12
void initialize(const QString &data)
Definition: qdlnaclient.cpp:49
The class of the dlna client private.
Definition: qdlnaclient.cpp:18
static const QString XML_HEAD
Definition: qdlnaclient.cpp:10
int GetResponseCode(const QString &data)
Definition: qdlnahelper.cpp:76
QDlnaService readServiceTag(const QString &type, const QString &tagName) const
Definition: qdlnaxml.cpp:82
QString startPlay(int instance)
#define TTK_INIT_PRIVATE(Class)
Definition: ttkprivate.h:33
The class of the ttk private base.
Definition: ttkprivate.h:48
static constexpr const char * AVTRANSPORT
Definition: qdlnaclient.cpp:8
QDlnaClient(const QString &data)
bool isConnected() const
bool fromString(const QString &data)
Definition: qdlnaxml.cpp:36
#define TTK_D(Class)
Definition: ttkprivate.h:41