From d23b42c1b3eef660accac57dd5c9ad43fa60c897 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 26 Sep 2021 22:11:22 +0200 Subject: [PATCH] added: parse JSON coming from kodi, if there is a notification that playback has started, switch on the amplifier --- src/ampswitch.cpp | 16 +++++++++++++++- src/ampswitch.h | 31 +++++++++++++++++-------------- src/kodiclient.cpp | 23 ++++++++++++++++++++--- src/kodiclient.h | 10 +++++++++- wscript | 1 + 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/ampswitch.cpp b/src/ampswitch.cpp index be48efa..38a1f3e 100644 --- a/src/ampswitch.cpp +++ b/src/ampswitch.cpp @@ -52,6 +52,7 @@ CAmpSwitch::CAmpSwitch(int argc, char *argv[]) m_switchedon = false; m_samplecounter = 0; m_usekodi = false; + m_playstart = false; struct option longoptions[] = { @@ -138,7 +139,7 @@ bool CAmpSwitch::Setup() printf("off command: \"%s\"\n", m_offcommand); 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; } @@ -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 bool trigger = fabsf(*(in++)) > m_triggerlevel; + + //Consider a playback start as a trigger. + if (m_playstart) + { + trigger = true; + m_playstart = false; + } + if (trigger) { m_samplecounter = std::max((int)lround(m_switchtime * m_samplerate), 1); @@ -381,3 +390,8 @@ void CAmpSwitch::SignalHandler(int signum) g_stop = true; } +void CAmpSwitch::SignalPlayStart() +{ + //Signal the jack client thread that playback has started. + m_playstart = true; +} diff --git a/src/ampswitch.h b/src/ampswitch.h index 60df974..88a972f 100644 --- a/src/ampswitch.h +++ b/src/ampswitch.h @@ -28,27 +28,29 @@ class CAmpSwitch CAmpSwitch(int argc, char *argv[]); ~CAmpSwitch(); - bool Setup(); - void Process(); - void Cleanup(); + bool Setup(); + void Process(); + void Cleanup(); + + void SignalPlayStart(); private: - void PrintHelpMessage(); + void PrintHelpMessage(); - void Connect(); - bool JackConnect(); - void JackDisconnect(); + void Connect(); + bool JackConnect(); + void JackDisconnect(); - static int SJackProcessCallback(jack_nframes_t nframes, void *arg); - int PJackProcessCallback(jack_nframes_t nframes); + static int SJackProcessCallback(jack_nframes_t nframes, void *arg); + int PJackProcessCallback(jack_nframes_t nframes); - static int SJackSamplerateCallback(jack_nframes_t nframes, void *arg); - int PJackSamplerateCallback(jack_nframes_t nframes); + static int SJackSamplerateCallback(jack_nframes_t nframes, void *arg); + int PJackSamplerateCallback(jack_nframes_t nframes); - static void SJackInfoShutdownCallback(jack_status_t code, const char *reason, void *arg); - void PJackInfoShutdownCallback(jack_status_t code, const char *reason); + static void SJackInfoShutdownCallback(jack_status_t code, const char *reason, void *arg); + void PJackInfoShutdownCallback(jack_status_t code, const char *reason); - static void SignalHandler(int signum); + static void SignalHandler(int signum); float m_triggerlevel; float m_switchtime; @@ -68,6 +70,7 @@ class CAmpSwitch bool m_usekodi; CKodiClient m_kodiclient; + bool m_playstart; }; #endif //AMPSWITCH_H diff --git a/src/kodiclient.cpp b/src/kodiclient.cpp index 748b511..a64832c 100644 --- a/src/kodiclient.cpp +++ b/src/kodiclient.cpp @@ -17,6 +17,7 @@ */ #include "kodiclient.h" +#include "ampswitch.h" #include #include @@ -24,14 +25,18 @@ #include #include +#include + using namespace boost::asio; using ip::tcp; using std::string; using std::cout; using std::endl; +using namespace nlohmann; -void CKodiClient::Start() +void CKodiClient::Start(CAmpSwitch* ampswitch) { + m_ampswitch = ampswitch; 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. 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. for(;;) { @@ -63,8 +70,18 @@ void CKodiClient::Process() size_t readbytes = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1)); const char* data = boost::asio::buffer_cast(receive_buffer.data()); - printf("Received %i bytes: %s\n", (int)readbytes, data); - printf("Data length: %i\n", (int)strlen(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")) + { + if (jsondata["method"] == "Player.OnPlay") + { + printf("Player started\n"); + m_ampswitch->SignalPlayStart(); + } + } } } catch(boost::system::system_error& error) diff --git a/src/kodiclient.h b/src/kodiclient.h index 3d0d993..c2a830c 100644 --- a/src/kodiclient.h +++ b/src/kodiclient.h @@ -16,16 +16,24 @@ * with this program. If not, see . */ +#ifndef KODICLIENT_H +#define KODICLIENT_H + #include +class CAmpSwitch; + class CKodiClient { public: - void Start(); + void Start(CAmpSwitch* ampswitch); private: static void SProcess(CKodiClient* kodiclient); void Process(); std::thread m_thread; + CAmpSwitch* m_ampswitch; }; + +#endif //KODICLIENT_H diff --git a/wscript b/wscript index f7a6eae..4363a6d 100644 --- a/wscript +++ b/wscript @@ -17,6 +17,7 @@ def configure(conf): conf.check(header_name='jack/jack.h') 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='pthread', uselib_store='pthread', mandatory=False)