added: parse JSON coming from kodi, if there is a notification that playback has started, switch on the amplifier

This commit is contained in:
Bob 2021-09-26 22:11:22 +02:00
parent 413f5ecf9d
commit d23b42c1b3
5 changed files with 62 additions and 19 deletions

View file

@ -52,6 +52,7 @@ CAmpSwitch::CAmpSwitch(int argc, char *argv[])
m_switchedon = false; m_switchedon = false;
m_samplecounter = 0; m_samplecounter = 0;
m_usekodi = false; m_usekodi = false;
m_playstart = false;
struct option longoptions[] = struct option longoptions[] =
{ {
@ -138,7 +139,7 @@ bool CAmpSwitch::Setup()
printf("off command: \"%s\"\n", m_offcommand); printf("off command: \"%s\"\n", m_offcommand);
if (m_usekodi) if (m_usekodi)
m_kodiclient.Start(); //start a thread that connects to Kodi's JSONRPC m_kodiclient.Start(this); //start a thread that connects to Kodi's JSONRPC
return true; return true;
} }
@ -321,6 +322,14 @@ int CAmpSwitch::PJackProcessCallback(jack_nframes_t nframes)
{ {
//if the absolute sample value is higher than the trigger level, set the switch state to on and reset the sample counter //if the absolute sample value is higher than the trigger level, set the switch state to on and reset the sample counter
bool trigger = fabsf(*(in++)) > m_triggerlevel; bool trigger = fabsf(*(in++)) > m_triggerlevel;
//Consider a playback start as a trigger.
if (m_playstart)
{
trigger = true;
m_playstart = false;
}
if (trigger) if (trigger)
{ {
m_samplecounter = std::max((int)lround(m_switchtime * m_samplerate), 1); m_samplecounter = std::max((int)lround(m_switchtime * m_samplerate), 1);
@ -381,3 +390,8 @@ void CAmpSwitch::SignalHandler(int signum)
g_stop = true; g_stop = true;
} }
void CAmpSwitch::SignalPlayStart()
{
//Signal the jack client thread that playback has started.
m_playstart = true;
}

View file

@ -28,27 +28,29 @@ class CAmpSwitch
CAmpSwitch(int argc, char *argv[]); CAmpSwitch(int argc, char *argv[]);
~CAmpSwitch(); ~CAmpSwitch();
bool Setup(); bool Setup();
void Process(); void Process();
void Cleanup(); void Cleanup();
void SignalPlayStart();
private: private:
void PrintHelpMessage(); void PrintHelpMessage();
void Connect(); void Connect();
bool JackConnect(); bool JackConnect();
void JackDisconnect(); void JackDisconnect();
static int SJackProcessCallback(jack_nframes_t nframes, void *arg); static int SJackProcessCallback(jack_nframes_t nframes, void *arg);
int PJackProcessCallback(jack_nframes_t nframes); int PJackProcessCallback(jack_nframes_t nframes);
static int SJackSamplerateCallback(jack_nframes_t nframes, void *arg); static int SJackSamplerateCallback(jack_nframes_t nframes, void *arg);
int PJackSamplerateCallback(jack_nframes_t nframes); int PJackSamplerateCallback(jack_nframes_t nframes);
static void SJackInfoShutdownCallback(jack_status_t code, const char *reason, void *arg); static void SJackInfoShutdownCallback(jack_status_t code, const char *reason, void *arg);
void PJackInfoShutdownCallback(jack_status_t code, const char *reason); void PJackInfoShutdownCallback(jack_status_t code, const char *reason);
static void SignalHandler(int signum); static void SignalHandler(int signum);
float m_triggerlevel; float m_triggerlevel;
float m_switchtime; float m_switchtime;
@ -68,6 +70,7 @@ class CAmpSwitch
bool m_usekodi; bool m_usekodi;
CKodiClient m_kodiclient; CKodiClient m_kodiclient;
bool m_playstart;
}; };
#endif //AMPSWITCH_H #endif //AMPSWITCH_H

View file

@ -17,6 +17,7 @@
*/ */
#include "kodiclient.h" #include "kodiclient.h"
#include "ampswitch.h"
#include <cstdio> #include <cstdio>
#include <unistd.h> #include <unistd.h>
@ -24,14 +25,18 @@
#include <iostream> #include <iostream>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <nlohmann/json.hpp>
using namespace boost::asio; using namespace boost::asio;
using ip::tcp; using ip::tcp;
using std::string; using std::string;
using std::cout; using std::cout;
using std::endl; using std::endl;
using namespace nlohmann;
void CKodiClient::Start() void CKodiClient::Start(CAmpSwitch* ampswitch)
{ {
m_ampswitch = ampswitch;
m_thread = std::thread(SProcess, this); m_thread = std::thread(SProcess, this);
} }
@ -56,6 +61,8 @@ void CKodiClient::Process()
//Connect to Kodi's JSONRPC, this will thrown an exception on failure. //Connect to Kodi's JSONRPC, this will thrown an exception on failure.
socket.connect(tcp::endpoint(address, 9090)); socket.connect(tcp::endpoint(address, 9090));
printf("Connected to Kodi\n");
//Keep reading data from Kodi, when the tcp socket is closed an exception is thrown. //Keep reading data from Kodi, when the tcp socket is closed an exception is thrown.
for(;;) for(;;)
{ {
@ -63,8 +70,18 @@ void CKodiClient::Process()
size_t readbytes = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1)); size_t readbytes = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1));
const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data()); const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data());
printf("Received %i bytes: %s\n", (int)readbytes, data); //TODO: because of TCP, one read does not exactly equal one JSON object.
printf("Data length: %i\n", (int)strlen(data)); json jsondata = json::parse(data);
//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();
}
}
} }
} }
catch(boost::system::system_error& error) catch(boost::system::system_error& error)

View file

@ -16,16 +16,24 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KODICLIENT_H
#define KODICLIENT_H
#include <thread> #include <thread>
class CAmpSwitch;
class CKodiClient class CKodiClient
{ {
public: public:
void Start(); void Start(CAmpSwitch* ampswitch);
private: private:
static void SProcess(CKodiClient* kodiclient); static void SProcess(CKodiClient* kodiclient);
void Process(); void Process();
std::thread m_thread; std::thread m_thread;
CAmpSwitch* m_ampswitch;
}; };
#endif //KODICLIENT_H

View file

@ -17,6 +17,7 @@ def configure(conf):
conf.check(header_name='jack/jack.h') conf.check(header_name='jack/jack.h')
conf.check(header_name='boost/asio.hpp') conf.check(header_name='boost/asio.hpp')
conf.check(header_name='nlohmann/json.hpp')
conf.check(lib='jack', uselib_store='jack', mandatory=True) conf.check(lib='jack', uselib_store='jack', mandatory=True)
conf.check(lib='pthread', uselib_store='pthread', mandatory=False) conf.check(lib='pthread', uselib_store='pthread', mandatory=False)