added: parse JSON coming from kodi, if there is a notification that playback has started, switch on the amplifier
This commit is contained in:
parent
413f5ecf9d
commit
d23b42c1b3
5 changed files with 62 additions and 19 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
1
wscript
1
wscript
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue