473 lines
11 KiB
C++
473 lines
11 KiB
C++
#include "AVReceiverDevice.h"
|
|
#include "GlobalDefine.h"
|
|
#include "ProtocolDefs.h"
|
|
#include <QDataStream>
|
|
|
|
|
|
/**
|
|
Command syntax
|
|
|
|
@ SUBUNIT : FUNCNAME = Parameter [CR/LF]
|
|
[1] [2] [3] [4] [5] [6] [7]
|
|
[1] Start Delimiter (@) : The beginning of a command
|
|
[2] Sub Unit Name : Indicating whether the command is for System, any zones or
|
|
any internal input sources as iPod, Tuner, Sirius, and
|
|
Rhapsody etc
|
|
[3] Command Delimiter (:) : Sub Unit Name and Function name are separated by this
|
|
delimiter
|
|
[4] Function Name : Specifying actual operations, some of them are abbreviated
|
|
[5] Parameter Delimiter (=) : Separating the Function Name and its Parameter (Value)
|
|
[6] Parameter : Showing a parameter value of the command
|
|
[7] End Delimiter : The end of a command, Carriage
|
|
*/
|
|
|
|
CAVReceiverDevice::CAVReceiverDevice()
|
|
{
|
|
mReceiverSocket = new QTcpSocket;
|
|
mDisconnectTimer = new QTimer;
|
|
mStateRequestTimer = new QTimer;
|
|
// mSyncDelayTimer = new QTimer;
|
|
|
|
mDisconnectTimer->setSingleShot(true);
|
|
mDisconnectTimer->stop();
|
|
|
|
mStateRequestTimer->setSingleShot(true);
|
|
mStateRequestTimer->setInterval(RECEIVER_STATE_UPDATE_TIMEOUT);
|
|
|
|
// mSyncDelayTimer->setSingleShot(true);
|
|
// mSyncDelayTimer->setInterval(500);
|
|
|
|
|
|
connect(mDisconnectTimer,SIGNAL(timeout()),this,SLOT(DisconnectTimerExpired()));
|
|
|
|
connect(mReceiverSocket,SIGNAL(connected()),this,SLOT(SocketConnected()));
|
|
connect(mReceiverSocket,SIGNAL(disconnected()),this,SLOT(SocketDisconnected()));
|
|
connect(mReceiverSocket,SIGNAL(readyRead()),this,SLOT(SocketRX()));
|
|
|
|
connect(mStateRequestTimer,SIGNAL(timeout()),this,SLOT(StateRequestTimerExpired()));
|
|
|
|
// connect(mSyncDelayTimer,&QTimer::timeout,this,&CAVReceiverDevice::SyncTimerExpired);
|
|
}
|
|
|
|
|
|
CAVReceiverDevice::~CAVReceiverDevice()
|
|
{
|
|
mReceiverSocket->disconnectFromHost();
|
|
mReceiverSocket->waitForDisconnected(100);
|
|
|
|
delete mReceiverSocket;
|
|
delete mDisconnectTimer;
|
|
delete mStateRequestTimer;
|
|
delete mSyncDelayTimer;
|
|
}
|
|
|
|
int CAVReceiverDevice::Start()
|
|
{
|
|
mStateRequestTimer->start();
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::ConnectToReceiver()
|
|
{
|
|
if(mReceiverSocket->state() != QAbstractSocket::ConnectedState)
|
|
{
|
|
mReceiverSocket->connectToHost("192.168.50.101",50000);
|
|
}
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::DisconnectReceiver()
|
|
{
|
|
if(mReceiverSocket->state() != QAbstractSocket::ConnectedState)
|
|
return RET_ERROR;
|
|
|
|
mReceiverSocket->disconnectFromHost();
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::AnalyseRxData(QByteArray data)
|
|
{
|
|
QString Data(data);
|
|
if(data == "\r\n")
|
|
{
|
|
// qDebug("AV Receiver: Heartbeat received");
|
|
return RET_OK;
|
|
}
|
|
|
|
QStringList Commands = Data.split("\r\n",QString::SkipEmptyParts);
|
|
|
|
|
|
for(int i = 0; i<Commands.size();i++)
|
|
{
|
|
QString Cmd = Commands.at(i);
|
|
Cmd.remove("@");
|
|
QString SubUnit = Cmd.left(Cmd.indexOf(QChar(':')));
|
|
Cmd.remove(SubUnit + ":");
|
|
QString Function = Cmd.left(Cmd.indexOf(QChar('=')));
|
|
Cmd.remove(Function + "=");
|
|
QString Param = Cmd.remove("\r\n");
|
|
|
|
UpdateReceiverStateParam(SubUnit,Function,Param);
|
|
|
|
// qDebug("Received SubUnit:[%s], Function:[%s], Param:[%s]",qPrintable(SubUnit),qPrintable(Function),qPrintable(Param));
|
|
|
|
}
|
|
|
|
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::UpdateReceiverStateParam(QString SubUnit, QString Fcn, QString Param)
|
|
{
|
|
static bool AllValid = false;
|
|
CAvReceiverMainStatus *UnitStatus = 0;
|
|
if(SubUnit == "MAIN")
|
|
{
|
|
UnitStatus = &mReceiverStatus;
|
|
}
|
|
else if(SubUnit == "ZONE2")
|
|
{
|
|
UnitStatus = &mZone2Status;
|
|
}
|
|
|
|
if(UnitStatus != 0)
|
|
{
|
|
if(Fcn == "PWR")
|
|
{
|
|
if(Param == "On")
|
|
{
|
|
UnitStatus->mMainPwrStatus = true;
|
|
}
|
|
else
|
|
UnitStatus->mMainPwrStatus = false;
|
|
}
|
|
if(Fcn == "SLEEP")
|
|
{
|
|
if(Param == "On")
|
|
{
|
|
UnitStatus->mMainSleepStatus = true;
|
|
}
|
|
else
|
|
{
|
|
UnitStatus->mMainSleepStatus = false;
|
|
}
|
|
}
|
|
else if(Fcn == "VOL")
|
|
{
|
|
bool OK;
|
|
float Vol = Param.toFloat(&OK);
|
|
if(OK)
|
|
{
|
|
UnitStatus->mMainVolume = Vol;
|
|
}
|
|
else
|
|
{
|
|
UnitStatus->mMainPwrStatus = 0xDEADBEEF;
|
|
}
|
|
}
|
|
else if(Fcn == "MUTE")
|
|
{
|
|
if(Param == "On")
|
|
{
|
|
UnitStatus->mIsMute = true;
|
|
}
|
|
else
|
|
{
|
|
UnitStatus->mIsMute = false;
|
|
}
|
|
}
|
|
else if (Fcn == "INP")
|
|
{
|
|
UnitStatus->mInput = Param;
|
|
}
|
|
else if (Fcn == "SOUNDPRG")
|
|
{
|
|
UnitStatus->mProgram = Param;
|
|
}
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SendReceiverCommand(QString Command)
|
|
{
|
|
//Make sure the escape sequence is correct.
|
|
// Command.remove("\r");
|
|
// Command.remove("\n");
|
|
// Command.append("\r\n");
|
|
|
|
|
|
if(mReceiverSocket->state() == QAbstractSocket::ConnectedState)
|
|
{
|
|
mReceiverSocket->write(Command.toUtf8());
|
|
// qDebug("Sent command to receiver : %s",qPrintable(mPendingCommand));
|
|
}
|
|
else
|
|
{
|
|
mPendingCommand = Command;
|
|
ConnectToReceiver();
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
|
|
void CAVReceiverDevice::SocketConnected()
|
|
{
|
|
if(mPendingCommand.isEmpty() == false)
|
|
{
|
|
QByteArray data =mPendingCommand.toLatin1();
|
|
int ret = mReceiverSocket->write(data);
|
|
// qDebug("Sent command to receiver : %s",qPrintable(mPendingCommand));
|
|
mPendingCommand.clear();
|
|
return;
|
|
}
|
|
|
|
qDebug("Receiver Connected");
|
|
}
|
|
|
|
void CAVReceiverDevice::SocketDisconnected()
|
|
{
|
|
// qDebug("Receiver Disconnected");
|
|
}
|
|
|
|
void CAVReceiverDevice::SocketRX()
|
|
{
|
|
// qDebug("Receiver response:");
|
|
QByteArray Data = mReceiverSocket->readAll();
|
|
// qDebug("%s",qPrintable(Data));
|
|
AnalyseRxData(Data);
|
|
|
|
}
|
|
|
|
void CAVReceiverDevice::DisconnectTimerExpired()
|
|
{
|
|
DisconnectReceiver();
|
|
mDisconnectTimer->stop();
|
|
}
|
|
|
|
int CAVReceiverDevice::DisconnectReceiverDelayed(int Delay)
|
|
{
|
|
if(Delay > 5000)
|
|
{
|
|
Delay = 5000;
|
|
}
|
|
|
|
mDisconnectTimer->start(Delay);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
void CAVReceiverDevice::StateRequestTimerExpired()
|
|
{
|
|
if(mReceiverSocket->state() != QAbstractSocket::ConnectedState)
|
|
{
|
|
SendReceiverCommand("@MAIN:BASIC=?\r\n@ZONE2:BASIC=?\r\n");
|
|
mStateRequestTimer->start(RECEIVER_STATE_UPDATE_TIMEOUT);
|
|
DisconnectReceiverDelayed(1000);
|
|
}
|
|
else
|
|
{
|
|
//A transaction is going on... wait and retry later
|
|
mStateRequestTimer->start(500);
|
|
}
|
|
}
|
|
|
|
////// Network Interface Implementation
|
|
|
|
int CAVReceiverDevice::SetZone2(bool OnOff)
|
|
{
|
|
QString Cmd = "@ZONE2:PWR=";
|
|
if(OnOff)
|
|
{
|
|
Cmd += "On\r\n";
|
|
}
|
|
else
|
|
Cmd += "Standby\r\n";
|
|
|
|
SendReceiverCommand(Cmd);
|
|
|
|
DisconnectReceiverDelayed();
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SetMainZone(bool OnOff)
|
|
{
|
|
QString Cmd = "@MAIN:PWR=";
|
|
if(OnOff)
|
|
{
|
|
Cmd += "On\r\n";
|
|
}
|
|
else
|
|
Cmd += "Standby\r\n";
|
|
|
|
SendReceiverCommand(Cmd);
|
|
DisconnectReceiverDelayed();
|
|
return RET_OK;
|
|
}
|
|
int CAVReceiverDevice::SetSpeakers(int SpeakerA, int SpeakerB)
|
|
{
|
|
//First, speaker A.
|
|
if(SpeakerA != RECEIVER_DONT_CHANGE_SPK)
|
|
{
|
|
QString Cmd = "@MAIN:SPEAKERA=";
|
|
if(SpeakerA == RECEIVER_SET_SPK_ON)
|
|
{
|
|
Cmd += "On\r\n";
|
|
}
|
|
else if(SpeakerA == RECEIVER_SET_SPK_OFF)
|
|
{
|
|
Cmd += "Off\r\n";
|
|
}
|
|
else if(SpeakerA == RECEVIVER_TOGGLE_SPK)
|
|
{
|
|
// if(mReceiverStatus.mSpeakerAState == true)
|
|
// {
|
|
// Cmd += "Off";
|
|
// }
|
|
// else
|
|
// {
|
|
// Cmd += "On";
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
qDebug("Got a SetSpeakers() command with invalid parameter for Speaker A. Weirds stuff!!");
|
|
}
|
|
|
|
SendReceiverCommand(Cmd);
|
|
}
|
|
|
|
//Then, speaker B.
|
|
if(SpeakerB != RECEIVER_DONT_CHANGE_SPK)
|
|
{
|
|
QString Cmd = "@MAIN:SPEAKERB=";
|
|
if(SpeakerB == RECEIVER_SET_SPK_ON)
|
|
{
|
|
Cmd += "On";
|
|
}
|
|
else if(SpeakerB == RECEIVER_SET_SPK_OFF)
|
|
{
|
|
Cmd += "Off";
|
|
}
|
|
else if(SpeakerB == RECEVIVER_TOGGLE_SPK)
|
|
{
|
|
// if(mReceiverStatus.mSpeakerAState == true)
|
|
// {
|
|
// Cmd += "Off";
|
|
// }
|
|
// else
|
|
// {
|
|
// Cmd += "On";
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
qDebug("Got a SetSpeakers() command with invalid parameter for Speaker B. Weirds stuff!!");
|
|
}
|
|
|
|
SendReceiverCommand(Cmd);
|
|
}
|
|
DisconnectReceiverDelayed();
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SendRawCommand(QString Cmd)
|
|
{
|
|
return SendReceiverCommand(Cmd);
|
|
DisconnectReceiverDelayed(2000);
|
|
|
|
}
|
|
|
|
QByteArray CAVReceiverDevice::GetReceiverStatus()
|
|
{
|
|
QByteArray StatusArray;
|
|
QDataStream Strm(&StatusArray,QIODevice::WriteOnly | QIODevice::Unbuffered);
|
|
Strm.device()->seek(0);
|
|
|
|
Strm << mReceiverStatus
|
|
<< mZone2Status ;
|
|
|
|
if(mReceiverStatus.mSyncZonesVolumes == true &&
|
|
( (mReceiverStatus.mMainVolume != mLastMainZoneVolume) ||
|
|
(mReceiverStatus.mMainVolume != mZone2Status.mMainVolume)))
|
|
{
|
|
SetZone2Volume(mReceiverStatus.mMainVolume);
|
|
}
|
|
|
|
mLastMainZoneVolume = mReceiverStatus.mMainVolume;
|
|
return StatusArray;
|
|
}
|
|
|
|
int CAVReceiverDevice::SelectScene(char Zone, char Scene)
|
|
{
|
|
QString Cmd;
|
|
if(Zone == AV_RECEIVER_MAIN_ZONE)
|
|
{
|
|
Cmd = QString("@MAIN:SCENE=Scene %1\r\n").arg((int)Scene,1);
|
|
|
|
}
|
|
else if(Zone == AV_RECEIVER_ZONE_2)
|
|
{
|
|
Cmd = QString("@ZONE2:SCENE=Scene %1\r\n").arg((int)Scene,1);
|
|
}
|
|
else
|
|
{
|
|
return RET_ERROR;
|
|
}
|
|
|
|
SendReceiverCommand(Cmd);
|
|
DisconnectReceiverDelayed(2000);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SetMainVolume(float Volume)
|
|
{
|
|
QString Cmd;
|
|
Cmd = QString("@MAIN:VOL=%1\r\n").arg(Volume,1,'f',1);
|
|
|
|
// qDebug("%s",qPrintable(Cmd));
|
|
|
|
SendReceiverCommand(Cmd);
|
|
// DisconnectReceiverDelayed();
|
|
|
|
if(mReceiverStatus.mSyncZonesVolumes == true)
|
|
{
|
|
SetZone2Volume(Volume);
|
|
}
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SetZone2Volume(float Volume)
|
|
{
|
|
QString Cmd;
|
|
Cmd = QString("@ZONE2:VOL=%1\r\n").arg(Volume,1,'f',1);
|
|
|
|
SendReceiverCommand(Cmd);
|
|
// DisconnectReceiverDelayed();
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SetZone2Input(QString InputString)
|
|
{
|
|
QString Cmd;
|
|
Cmd = QString("@ZONE2:INP=%1\r\n").arg(InputString);
|
|
|
|
SendReceiverCommand(Cmd);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
int CAVReceiverDevice::SetSyncZ2withZ1(bool Sync)
|
|
{
|
|
mReceiverStatus.mSyncZonesVolumes = Sync;
|
|
if(Sync == true)
|
|
{
|
|
SetZone2Volume(mReceiverStatus.mMainVolume);
|
|
}
|
|
// qDebug("Sync Z2 with Z1: %d",Sync);
|
|
}
|