fixed: get full json objects from the tcp stream, and parse them
This commit is contained in:
parent
fd151cf7df
commit
0f32809b74
2 changed files with 68 additions and 9 deletions
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/asio.hpp>
|
||||
|
@ -61,22 +62,63 @@ void CKodiClient::Process()
|
|||
printf("Connected to Kodi\n");
|
||||
|
||||
//Keep reading data from Kodi, when the tcp socket is closed an exception is thrown.
|
||||
uint32_t bracketlevel = 0;
|
||||
bool instring = false;
|
||||
bool escaped = false;
|
||||
std::string jsonstr;
|
||||
for(;;)
|
||||
{
|
||||
boost::asio::streambuf receive_buffer;
|
||||
size_t readbytes = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1));
|
||||
size_t bytesread = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1));
|
||||
|
||||
const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data());
|
||||
|
||||
//TODO: because of TCP, one read does not exactly equal one JSON object.
|
||||
json jsondata = json::parse(data);
|
||||
|
||||
//If Kodi signals a Player.OnPlay notification, the amplifier should be turned on.
|
||||
if (jsondata.contains("method"))
|
||||
//Parse the JSON data into separate JSON objects by finding the text from
|
||||
//the starting { to ending }, while ignoring curly brackets in strings.
|
||||
for (uint32_t i = 0; i < (uint32_t)bytesread; i++)
|
||||
{
|
||||
if (jsondata["method"] == "Player.OnPlay")
|
||||
jsonstr.push_back(data[i]);
|
||||
|
||||
if (!instring)
|
||||
{
|
||||
printf("Player started\n");
|
||||
m_ampswitch->SignalPlayStart();
|
||||
if (data[i] == '"')
|
||||
{
|
||||
instring = true;
|
||||
}
|
||||
else if (data[i] == '{')
|
||||
{
|
||||
bracketlevel++;
|
||||
}
|
||||
else if (data[i] == '}')
|
||||
{
|
||||
if (bracketlevel > 0)
|
||||
{
|
||||
bracketlevel--;
|
||||
if (bracketlevel == 0)
|
||||
{
|
||||
Parse(jsonstr);
|
||||
jsonstr.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonstr.clear(); //Shouldn't happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!escaped)
|
||||
{
|
||||
if (data[i] == '\\')
|
||||
escaped = true;
|
||||
else if (data[i] == '"')
|
||||
instring = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
escaped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,3 +131,18 @@ void CKodiClient::Process()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CKodiClient::Parse(const std::string& jsonstr)
|
||||
{
|
||||
json jsondata = json::parse(jsonstr);
|
||||
|
||||
//If Kodi signals a Player.OnPlay notification, the amplifier should be turned on.
|
||||
if (jsondata.contains("method"))
|
||||
{
|
||||
if (jsondata["method"] == "Player.OnPlay")
|
||||
{
|
||||
printf("Player started\n");
|
||||
m_ampswitch->SignalPlayStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define KODICLIENT_H
|
||||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
|
||||
class CAmpSwitch;
|
||||
|
||||
|
@ -31,6 +32,7 @@ class CKodiClient
|
|||
private:
|
||||
static void SProcess(CKodiClient* kodiclient);
|
||||
void Process();
|
||||
void Parse(const std::string& jsonstr);
|
||||
|
||||
std::thread m_thread;
|
||||
CAmpSwitch* m_ampswitch;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue