Add dynamic TG voice prompts and status TG.

This commit is contained in:
Jonathan Naylor
2020-04-03 16:54:35 +01:00
parent 9771b1ff0c
commit 0fef073c13
16 changed files with 651 additions and 151 deletions

View File

@@ -410,14 +410,16 @@ bool CConf::read()
char* p2 = ::strtok(NULL, ", ");
char* p3 = ::strtok(NULL, ", ");
char* p4 = ::strtok(NULL, ", ");
char* p5 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) {
char* p5 = ::strtok(NULL, ", ");
char* p6 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
CTGDynRewriteStruct rewrite;
rewrite.m_slot = ::atoi(p1);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discTG = ::atoi(p3);
rewrite.m_toTG = ::atoi(p4);
rewrite.m_range = ::atoi(p5);
rewrite.m_statusTG = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
m_dmrNetwork1TGDynRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "IdRewrite", 9U) == 0) {
@@ -520,14 +522,16 @@ bool CConf::read()
char* p2 = ::strtok(NULL, ", ");
char* p3 = ::strtok(NULL, ", ");
char* p4 = ::strtok(NULL, ", ");
char* p5 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) {
char* p5 = ::strtok(NULL, ", ");
char* p6 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
CTGDynRewriteStruct rewrite;
rewrite.m_slot = ::atoi(p1);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discTG = ::atoi(p3);
rewrite.m_toTG = ::atoi(p4);
rewrite.m_range = ::atoi(p5);
rewrite.m_statusTG = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
m_dmrNetwork2TGDynRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "IdRewrite", 9U) == 0) {
@@ -630,14 +634,16 @@ bool CConf::read()
char* p2 = ::strtok(NULL, ", ");
char* p3 = ::strtok(NULL, ", ");
char* p4 = ::strtok(NULL, ", ");
char* p5 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) {
char* p5 = ::strtok(NULL, ", ");
char* p6 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
CTGDynRewriteStruct rewrite;
rewrite.m_slot = ::atoi(p1);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discTG = ::atoi(p3);
rewrite.m_toTG = ::atoi(p4);
rewrite.m_range = ::atoi(p5);
rewrite.m_statusTG = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
m_dmrNetwork3TGDynRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "IdRewrite", 9U) == 0) {
@@ -740,14 +746,16 @@ bool CConf::read()
char* p2 = ::strtok(NULL, ", ");
char* p3 = ::strtok(NULL, ", ");
char* p4 = ::strtok(NULL, ", ");
char* p5 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) {
char* p5 = ::strtok(NULL, ", ");
char* p6 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
CTGDynRewriteStruct rewrite;
rewrite.m_slot = ::atoi(p1);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discTG = ::atoi(p3);
rewrite.m_toTG = ::atoi(p4);
rewrite.m_range = ::atoi(p5);
rewrite.m_statusTG = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
m_dmrNetwork4TGDynRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "IdRewrite", 9U) == 0) {
@@ -850,14 +858,16 @@ bool CConf::read()
char* p2 = ::strtok(NULL, ", ");
char* p3 = ::strtok(NULL, ", ");
char* p4 = ::strtok(NULL, ", ");
char* p5 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) {
char* p5 = ::strtok(NULL, ", ");
char* p6 = ::strtok(NULL, " \r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
CTGDynRewriteStruct rewrite;
rewrite.m_slot = ::atoi(p1);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discTG = ::atoi(p3);
rewrite.m_toTG = ::atoi(p4);
rewrite.m_range = ::atoi(p5);
rewrite.m_statusTG = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
m_dmrNetwork5TGDynRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "IdRewrite", 9U) == 0) {

1
Conf.h
View File

@@ -57,6 +57,7 @@ struct CTGDynRewriteStruct {
unsigned int m_slot;
unsigned int m_fromTG;
unsigned int m_discTG;
unsigned int m_statusTG;
unsigned int m_toTG;
unsigned int m_range;
};

View File

@@ -370,47 +370,16 @@ int CDMRGateway::run()
bool ruleTrace = m_conf.getRuleTrace();
LogInfo("Rule trace: %s", ruleTrace ? "yes" : "no");
if (m_conf.getDMRNetwork1Enabled()) {
ret = createDMRNetwork1();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork2Enabled()) {
ret = createDMRNetwork2();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork3Enabled()) {
ret = createDMRNetwork3();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork4Enabled()) {
ret = createDMRNetwork4();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork5Enabled()) {
ret = createDMRNetwork5();
if (!ret)
return 1;
}
if (m_conf.getXLXNetworkEnabled()) {
ret = createXLXNetwork();
if (!ret)
return 1;
}
unsigned int rfTimeout = m_conf.getRFTimeout();
unsigned int netTimeout = m_conf.getNetTimeout();
CXLXVoice* xlxVoice = NULL;
CDynVoice* dynVoice = NULL;
CXLXVoice* voice = NULL;
if (m_conf.getVoiceEnabled() && m_xlxNetwork != NULL) {
if (m_conf.getVoiceEnabled()) {
std::string language = m_conf.getVoiceLanguage();
std::string directory = m_conf.getVoiceDirectory();
@@ -419,14 +388,56 @@ int CDMRGateway::run()
LogInfo(" Language: %s", language.c_str());
LogInfo(" Directory: %s", directory.c_str());
voice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG);
bool ret = voice->open();
if (m_xlxNetwork != NULL) {
xlxVoice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG);
bool ret = xlxVoice->open();
if (!ret) {
delete voice;
voice = NULL;
delete xlxVoice;
xlxVoice = NULL;
}
}
dynVoice = new CDynVoice(directory, language, m_repeater->getId());
bool ret = dynVoice->open();
if (!ret) {
delete dynVoice;
dynVoice = NULL;
}
}
if (m_conf.getDMRNetwork1Enabled()) {
ret = createDMRNetwork1(dynVoice);
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork2Enabled()) {
ret = createDMRNetwork2(dynVoice);
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork3Enabled()) {
ret = createDMRNetwork3(dynVoice);
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork4Enabled()) {
ret = createDMRNetwork4(dynVoice);
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork5Enabled()) {
ret = createDMRNetwork5(dynVoice);
if (!ret)
return 1;
}
unsigned int rfTimeout = m_conf.getRFTimeout();
unsigned int netTimeout = m_conf.getNetTimeout();
CTimer* timer[3U];
timer[1U] = new CTimer(1000U);
timer[2U] = new CTimer(1000U);
@@ -468,18 +479,18 @@ int CDMRGateway::run()
writeXLXLink(m_xlxId, m_xlxReflector, m_xlxNetwork);
char c = ('A' + (m_xlxReflector % 100U)) - 1U;
LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c);
if (voice != NULL)
voice->linkedTo(m_xlxNumber, m_xlxReflector);
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
} else if (m_xlxRoom >= 4001U && m_xlxRoom <= 4026U) {
writeXLXLink(m_xlxId, m_xlxRoom, m_xlxNetwork);
char c = ('A' + (m_xlxRoom % 100U)) - 1U;
LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c);
if (voice != NULL)
voice->linkedTo(m_xlxNumber, m_xlxRoom);
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, m_xlxRoom);
m_xlxReflector = m_xlxRoom;
} else {
if (voice != NULL)
voice->linkedTo(m_xlxNumber, 0U);
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, 0U);
}
m_xlxConnected = true;
@@ -491,8 +502,8 @@ int CDMRGateway::run()
} else if (!connected && m_xlxConnected) {
LogMessage("XLX, Unlinking from XLX%03u due to loss of connection", m_xlxNumber);
if (voice != NULL)
voice->unlinked();
if (xlxVoice != NULL)
xlxVoice->unlinked();
m_xlxConnected = false;
m_xlxRelink.stop();
@@ -523,11 +534,11 @@ int CDMRGateway::run()
}
m_xlxReflector = m_xlxRoom;
if (voice != NULL) {
if (xlxVoice != NULL) {
if (m_xlxReflector < 4001U || m_xlxReflector > 4026U)
voice->linkedTo(m_xlxNumber, 0U);
xlxVoice->linkedTo(m_xlxNumber, 0U);
else
voice->linkedTo(m_xlxNumber, m_xlxReflector);
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
}
}
}
@@ -580,16 +591,16 @@ int CDMRGateway::run()
timer[slotNo]->setTimeout(rfTimeout);
timer[slotNo]->start();
if (voice != NULL) {
if (xlxVoice != NULL) {
unsigned char type = data.getDataType();
if (type == DT_TERMINATOR_WITH_LC) {
if (m_xlxConnected) {
if (m_xlxReflector != 4000U)
voice->linkedTo(m_xlxNumber, m_xlxReflector);
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
else
voice->linkedTo(m_xlxNumber, 0U);
xlxVoice->linkedTo(m_xlxNumber, 0U);
} else {
voice->unlinked();
xlxVoice->unlinked();
}
}
}
@@ -1111,8 +1122,8 @@ int CDMRGateway::run()
processHomePosition();
if (voice != NULL) {
ret = voice->read(data);
if (xlxVoice != NULL) {
ret = xlxVoice->read(data);
if (ret) {
m_repeater->write(data);
m_status[m_xlxSlot] = DMRGWS_XLXREFLECTOR;
@@ -1121,6 +1132,12 @@ int CDMRGateway::run()
}
}
if (dynVoice != NULL) {
ret = dynVoice->read(data);
if (ret)
m_repeater->write(data);
}
unsigned int ms = stopWatch.elapsed();
stopWatch.start();
@@ -1149,8 +1166,11 @@ int CDMRGateway::run()
if (m_xlxReflectors != NULL)
m_xlxReflectors->clock(ms);
if (voice != NULL)
voice->clock(ms);
if (xlxVoice != NULL)
xlxVoice->clock(ms);
if (dynVoice != NULL)
dynVoice->clock(ms);
for (unsigned int i = 1U; i < 3U; i++) {
timer[i]->clock(ms);
@@ -1164,7 +1184,8 @@ int CDMRGateway::run()
CThread::sleep(10U);
}
delete voice;
delete xlxVoice;
delete dynVoice;
m_repeater->close();
delete m_repeater;
@@ -1233,7 +1254,7 @@ bool CDMRGateway::createMMDVM()
return true;
}
bool CDMRGateway::createDMRNetwork1()
bool CDMRGateway::createDMRNetwork1(CDynVoice* voice)
{
std::string address = m_conf.getDMRNetwork1Address();
unsigned int port = m_conf.getDMRNetwork1Port();
@@ -1337,10 +1358,10 @@ bool CDMRGateway::createDMRNetwork1()
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork1TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) {
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG);
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG);
CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_toTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice);
m_dmr1RFRewrites.push_back(rfRewriteDynTG);
m_dmr1NetRewrites.push_back(netRewriteDynTG);
@@ -1382,7 +1403,7 @@ bool CDMRGateway::createDMRNetwork1()
return true;
}
bool CDMRGateway::createDMRNetwork2()
bool CDMRGateway::createDMRNetwork2(CDynVoice* voice)
{
std::string address = m_conf.getDMRNetwork2Address();
unsigned int port = m_conf.getDMRNetwork2Port();
@@ -1486,10 +1507,10 @@ bool CDMRGateway::createDMRNetwork2()
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork2TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) {
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG);
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG);
CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_toTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice);
m_dmr2RFRewrites.push_back(rfRewriteDynTG);
m_dmr2NetRewrites.push_back(netRewriteDynTG);
@@ -1531,7 +1552,7 @@ bool CDMRGateway::createDMRNetwork2()
return true;
}
bool CDMRGateway::createDMRNetwork3()
bool CDMRGateway::createDMRNetwork3(CDynVoice* voice)
{
std::string address = m_conf.getDMRNetwork3Address();
unsigned int port = m_conf.getDMRNetwork3Port();
@@ -1635,10 +1656,10 @@ bool CDMRGateway::createDMRNetwork3()
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork3TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) {
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG);
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG);
CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_toTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice);
m_dmr3RFRewrites.push_back(rfRewriteDynTG);
m_dmr3NetRewrites.push_back(netRewriteDynTG);
@@ -1680,7 +1701,7 @@ bool CDMRGateway::createDMRNetwork3()
return true;
}
bool CDMRGateway::createDMRNetwork4()
bool CDMRGateway::createDMRNetwork4(CDynVoice* voice)
{
std::string address = m_conf.getDMRNetwork4Address();
unsigned int port = m_conf.getDMRNetwork4Port();
@@ -1784,10 +1805,10 @@ bool CDMRGateway::createDMRNetwork4()
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork4TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) {
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG);
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG);
CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_toTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice);
m_dmr4RFRewrites.push_back(rfRewriteDynTG);
m_dmr4NetRewrites.push_back(netRewriteDynTG);
@@ -1829,7 +1850,7 @@ bool CDMRGateway::createDMRNetwork4()
return true;
}
bool CDMRGateway::createDMRNetwork5()
bool CDMRGateway::createDMRNetwork5(CDynVoice* voice)
{
std::string address = m_conf.getDMRNetwork5Address();
unsigned int port = m_conf.getDMRNetwork5Port();
@@ -1933,10 +1954,10 @@ bool CDMRGateway::createDMRNetwork5()
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork5TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) {
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG);
LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG);
CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_toTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG);
CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice);
m_dmr5RFRewrites.push_back(rfRewriteDynTG);
m_dmr5NetRewrites.push_back(netRewriteDynTG);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2019 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2019,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
#include "DMRNetwork.h"
#include "Reflectors.h"
#include "RewriteTG.h"
#include "DynVoice.h"
#include "Rewrite.h"
#include "Timer.h"
#include "Conf.h"
@@ -106,11 +107,11 @@ private:
std::vector<CRewrite*> m_dmr5Passalls;
bool createMMDVM();
bool createDMRNetwork1();
bool createDMRNetwork2();
bool createDMRNetwork3();
bool createDMRNetwork4();
bool createDMRNetwork5();
bool createDMRNetwork1(CDynVoice* voice);
bool createDMRNetwork2(CDynVoice* voice);
bool createDMRNetwork3(CDynVoice* voice);
bool createDMRNetwork4(CDynVoice* voice);
bool createDMRNetwork5(CDynVoice* voice);
bool createXLXNetwork();
bool linkXLX(unsigned int number);

View File

@@ -54,7 +54,7 @@ UserControl=1
# BrandMeister
[DMR Network 1]
Enabled=1
Enabled=0
Name=BM
Address=44.131.4.1
Port=62031
@@ -71,7 +71,7 @@ SrcRewrite=1,9990,1,9990,1
# Reflector status returns
SrcRewrite=2,4000,2,9,1001
# Dynamic rewriting of slot 2 TGs 23500-23599 to TG9 to emulate reflector behaviour
TGDynRewrite=2,23500,4000,9,100
TGDynRewrite=2,23500,4000,5000,9,100
# Pass all of the other private traffic on slot 1 and slot 2
PassAllPC=1
PassAllPC=2

View File

@@ -166,6 +166,7 @@
<ClInclude Include="DMRLC.h" />
<ClInclude Include="DMRNetwork.h" />
<ClInclude Include="DMRSlotType.h" />
<ClInclude Include="DynVoice.h" />
<ClInclude Include="Golay2087.h" />
<ClInclude Include="Hamming.h" />
<ClInclude Include="Log.h" />
@@ -210,6 +211,7 @@
<ClCompile Include="DMRLC.cpp" />
<ClCompile Include="DMRNetwork.cpp" />
<ClCompile Include="DMRSlotType.cpp" />
<ClCompile Include="DynVoice.cpp" />
<ClCompile Include="Golay2087.cpp" />
<ClCompile Include="Hamming.cpp" />
<ClCompile Include="Log.cpp" />

View File

@@ -140,6 +140,9 @@
<ClInclude Include="XLXVoice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DynVoice.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Conf.cpp">
@@ -262,5 +265,8 @@
<ClCompile Include="XLXVoice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DynVoice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

345
DynVoice.cpp Normal file
View File

@@ -0,0 +1,345 @@
/*
* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "DMRSlotType.h"
#include "DMRFullLC.h"
#include "DynVoice.h"
#include "DMREMB.h"
#include "Sync.h"
#include "Log.h"
#include <cstring>
#include <cstdlib>
#include <sys/stat.h>
const unsigned char SILENCE[] = {0xACU, 0xAAU, 0x40U, 0x20U, 0x00U, 0x44U, 0x40U, 0x80U, 0x80U};
const unsigned char COLOR_CODE = 3U;
const unsigned int SILENCE_LENGTH = 9U;
const unsigned int AMBE_LENGTH = 9U;
CDynVoice::CDynVoice(const std::string& directory, const std::string& language, unsigned int id) :
m_indxFile(),
m_ambeFile(),
m_id(id),
m_slot(0U),
m_lc(),
m_embeddedLC(),
m_status(DYNVS_NONE),
m_timer(1000U, 1U),
m_stopWatch(),
m_seqNo(0U),
m_streamId(0U),
m_sent(0U),
m_ambe(NULL),
m_positions(),
m_data(),
m_it()
{
#if defined(_WIN32) || defined(_WIN64)
m_indxFile = directory + "\\" + language + ".indx";
m_ambeFile = directory + "\\" + language + ".ambe";
#else
m_indxFile = directory + "/" + language + ".indx";
m_ambeFile = directory + "/" + language + ".ambe";
#endif
}
CDynVoice::~CDynVoice()
{
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
for (std::unordered_map<std::string, CDynPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
delete it->second;
m_data.clear();
m_positions.clear();
delete[] m_ambe;
}
void CDynVoice::setSlotAndTG(unsigned int slot, unsigned int tg)
{
m_slot = slot;
m_lc.setFLCO(FLCO_GROUP);
m_lc.setSrcId(m_id);
m_lc.setDstId(tg);
m_embeddedLC.setLC(m_lc);
}
bool CDynVoice::open()
{
FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt");
if (fpindx == NULL) {
LogError("Unable to open the index file - %s", m_indxFile.c_str());
return false;
}
struct stat statStruct;
int ret = ::stat(m_ambeFile.c_str(), &statStruct);
if (ret != 0) {
LogError("Unable to stat the AMBE file - %s", m_ambeFile.c_str());
::fclose(fpindx);
return false;
}
FILE* fpambe = ::fopen(m_ambeFile.c_str(), "rb");
if (fpambe == NULL) {
LogError("Unable to open the AMBE file - %s", m_ambeFile.c_str());
::fclose(fpindx);
return false;
}
m_ambe = new unsigned char[statStruct.st_size];
size_t sizeRead = ::fread(m_ambe, 1U, statStruct.st_size, fpambe);
if (sizeRead != 0U) {
char buffer[80U];
while (::fgets(buffer, 80, fpindx) != NULL) {
char* p1 = ::strtok(buffer, "\t\r\n");
char* p2 = ::strtok(NULL, "\t\r\n");
char* p3 = ::strtok(NULL, "\t\r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL) {
std::string symbol = std::string(p1);
unsigned int start = ::atoi(p2) * AMBE_LENGTH;
unsigned int length = ::atoi(p3) * AMBE_LENGTH;
CDynPositions* pos = new CDynPositions;
pos->m_start = start;
pos->m_length = length;
m_positions[symbol] = pos;
}
}
}
::fclose(fpindx);
::fclose(fpambe);
return true;
}
void CDynVoice::linkedTo(unsigned int number)
{
char letters[10U];
::sprintf(letters, "%u", number);
std::vector<std::string> words;
if (m_positions.count("linkedto") == 0U) {
words.push_back("linked");
words.push_back("2");
} else {
words.push_back("linkedto");
}
for (unsigned int i = 0U; letters[i] != '\0'; i++)
words.push_back(std::string(1U, letters[i]));
createVoice(words);
}
void CDynVoice::unlinked()
{
std::vector<std::string> words;
words.push_back("notlinked");
createVoice(words);
}
void CDynVoice::createVoice(const std::vector<std::string>& words)
{
unsigned int ambeLength = 0U;
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
if (m_positions.count(*it) > 0U) {
CDynPositions* position = m_positions.at(*it);
ambeLength += position->m_length;
} else {
LogWarning("Unable to find character/phrase \"%s\" in the index", (*it).c_str());
}
}
// Ensure that the AMBE is an integer number of DMR frames
if ((ambeLength % (3U * AMBE_LENGTH)) != 0U) {
unsigned int frames = ambeLength / (3U * AMBE_LENGTH);
frames++;
ambeLength = frames * (3U * AMBE_LENGTH);
}
// Add space for silence before and after the voice
ambeLength += SILENCE_LENGTH * AMBE_LENGTH;
ambeLength += SILENCE_LENGTH * AMBE_LENGTH;
unsigned char* ambeData = new unsigned char[ambeLength];
// Fill the AMBE data with silence
for (unsigned int i = 0U; i < ambeLength; i += AMBE_LENGTH)
::memcpy(ambeData + i, SILENCE, AMBE_LENGTH);
// Put offset in for silence at the beginning
unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH;
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
if (m_positions.count(*it) > 0U) {
CDynPositions* position = m_positions.at(*it);
unsigned int start = position->m_start;
unsigned int length = position->m_length;
::memcpy(ambeData + pos, m_ambe + start, length);
pos += length;
}
}
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
m_streamId = ::rand() + 1U;
m_seqNo = 0U;
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
unsigned char buffer[DMR_FRAME_LENGTH_BYTES];
unsigned int n = 0U;
for (unsigned int i = 0U; i < ambeLength; i += (3U * AMBE_LENGTH)) {
unsigned char* p = ambeData + i;
CDMRData* data = new CDMRData;
data->setSlotNo(m_slot);
data->setFLCO(FLCO_GROUP);
data->setSrcId(m_lc.getSrcId());
data->setDstId(m_lc.getDstId());
data->setN(n);
data->setSeqNo(m_seqNo++);
data->setStreamId(m_streamId);
::memcpy(buffer + 0U, p + 0U, AMBE_LENGTH);
::memcpy(buffer + 9U, p + 9U, AMBE_LENGTH);
::memcpy(buffer + 15U, p + 9U, AMBE_LENGTH);
::memcpy(buffer + 24U, p + 18U, AMBE_LENGTH);
if (n == 0U) {
CSync::addDMRAudioSync(buffer, true);
data->setDataType(DT_VOICE_SYNC);
} else {
unsigned char lcss = m_embeddedLC.getData(buffer, n);
CDMREMB emb;
emb.setColorCode(COLOR_CODE);
emb.setPI(false);
emb.setLCSS(lcss);
emb.getData(buffer);
data->setDataType(DT_VOICE);
}
n++;
if (n >= 6U)
n = 0U;
data->setData(buffer);
m_data.push_back(data);
}
createHeaderTerminator(DT_TERMINATOR_WITH_LC);
createHeaderTerminator(DT_TERMINATOR_WITH_LC);
delete[] ambeData;
m_status = DYNVS_WAITING;
m_timer.start();
}
bool CDynVoice::read(CDMRData& data)
{
if (m_status != DYNVS_SENDING)
return false;
unsigned int count = m_stopWatch.elapsed() / DMR_SLOT_TIME;
if (m_sent < count) {
data = *(*m_it);
++m_sent;
++m_it;
if (m_it == m_data.end()) {
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
m_timer.stop();
m_status = DYNVS_NONE;
}
return true;
}
return false;
}
void CDynVoice::clock(unsigned int ms)
{
m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
if (m_status == DYNVS_WAITING) {
m_stopWatch.start();
m_status = DYNVS_SENDING;
m_it = m_data.begin();
m_sent = 0U;
}
}
}
void CDynVoice::createHeaderTerminator(unsigned char type)
{
CDMRData* data = new CDMRData;
data->setSlotNo(m_slot);
data->setFLCO(FLCO_GROUP);
data->setSrcId(m_lc.getSrcId());
data->setDstId(m_lc.getDstId());
data->setDataType(type);
data->setN(0U);
data->setSeqNo(m_seqNo++);
data->setStreamId(m_streamId);
unsigned char buffer[DMR_FRAME_LENGTH_BYTES];
CDMRFullLC fullLC;
fullLC.encode(m_lc, buffer, type);
CDMRSlotType slotType;
slotType.setColorCode(COLOR_CODE);
slotType.setDataType(type);
slotType.getData(buffer);
CSync::addDMRDataSync(buffer, true);
data->setData(buffer);
m_data.push_back(data);
}

81
DynVoice.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(DynVoice_H)
#define DynVoice_H
#include "DMREmbeddedData.h"
#include "StopWatch.h"
#include "DMRData.h"
#include "DMRLC.h"
#include "Timer.h"
#include <string>
#include <vector>
#include <unordered_map>
enum DYNVOICE_STATUS {
DYNVS_NONE,
DYNVS_WAITING,
DYNVS_SENDING
};
struct CDynPositions {
unsigned int m_start;
unsigned int m_length;
};
class CDynVoice {
public:
CDynVoice(const std::string& directory, const std::string& language, unsigned int id);
~CDynVoice();
void setSlotAndTG(unsigned int slot, unsigned int tg);
bool open();
void linkedTo(unsigned int number);
void unlinked();
bool read(CDMRData& data);
void clock(unsigned int ms);
private:
std::string m_indxFile;
std::string m_ambeFile;
unsigned int m_id;
unsigned int m_slot;
CDMRLC m_lc;
CDMREmbeddedData m_embeddedLC;
DYNVOICE_STATUS m_status;
CTimer m_timer;
CStopWatch m_stopWatch;
unsigned int m_seqNo;
unsigned int m_streamId;
unsigned int m_sent;
unsigned char* m_ambe;
std::unordered_map<std::string, CDynPositions*> m_positions;
std::vector<CDMRData*> m_data;
std::vector<CDMRData*>::const_iterator m_it;
void createHeaderTerminator(unsigned char type);
void createVoice(const std::vector<std::string>& words);
};
#endif

View File

@@ -5,9 +5,9 @@ LIBS = -lpthread
LDFLAGS = -g
OBJECTS = BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o DMRLC.o DMRNetwork.o DMRSlotType.o \
Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o \
RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o \
Utils.o XLXVoice.o
DynVoice.o Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o \
RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o \
Timer.o UDPSocket.o Utils.o XLXVoice.o
all: DMRGateway

View File

@@ -24,7 +24,7 @@
#include <cstdio>
#include <cassert>
CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet) :
CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) :
CRewrite(),
m_name(name),
m_slot(slot),
@@ -32,11 +32,16 @@ m_fromTGStart(fromTG),
m_fromTGEnd(fromTG + range - 1U),
m_toTG(toTG),
m_discTG(discTG),
m_statusTG(statusTG),
m_rewriteNet(rewriteNet),
m_voice(voice),
m_currentTG(0U)
{
assert(slot == 1U || slot == 2U);
assert(rewriteNet != NULL);
if (voice != NULL)
voice->setSlotAndTG(slot, toTG);
}
CRewriteDynTGRF::~CRewriteDynTGRF()
@@ -48,6 +53,7 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace)
FLCO flco = data.getFLCO();
unsigned int dstId = data.getDstId();
unsigned int slotNo = data.getSlotNo();
unsigned char type = data.getDataType();
if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_toTG && m_currentTG != 0U) {
data.setDstId(m_currentTG);
@@ -64,13 +70,17 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace)
if (trace)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_discTG);
if (type == DT_TERMINATOR_WITH_LC) {
m_rewriteNet->setCurrentTG(0U);
m_currentTG = 0U;
if (m_voice != NULL)
m_voice->unlinked();
}
return RESULT_MATCHED;
}
if (flco == FLCO_GROUP && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) {
if (slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) {
if (trace) {
if (m_fromTGStart == m_fromTGEnd)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart);
@@ -78,17 +88,37 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd);
}
data.setFLCO(FLCO_GROUP);
if (type == DT_TERMINATOR_WITH_LC) {
m_rewriteNet->setCurrentTG(dstId);
m_currentTG = dstId;
if (m_voice != NULL)
m_voice->linkedTo(dstId);
}
return RESULT_MATCHED;
}
if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_statusTG) {
if (trace)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_statusTG);
if (type == DT_TERMINATOR_WITH_LC && m_voice != NULL) {
if (m_currentTG == 0U)
m_voice->unlinked();
else
m_voice->linkedTo(dstId);
}
return RESULT_IGNORED;
}
if (trace) {
if (m_fromTGStart == m_fromTGEnd)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG);
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG, m_statusTG);
else
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG);
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG, m_statusTG);
}
return RESULT_UNMATCHED;

View File

@@ -19,6 +19,7 @@
#if !defined(REWRITEDYNTGRF_H)
#define REWRITEDYNTGRF_H
#include "DynVoice.h"
#include "Rewrite.h"
#include "DMRData.h"
@@ -28,7 +29,7 @@
class CRewriteDynTGRF : public CRewrite {
public:
CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet);
CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice);
virtual ~CRewriteDynTGRF();
virtual PROCESS_RESULT process(CDMRData& data, bool trace);
@@ -40,7 +41,9 @@ private:
unsigned int m_fromTGEnd;
unsigned int m_toTG;
unsigned int m_discTG;
unsigned int m_statusTG;
CRewriteDynTGNet* m_rewriteNet;
CDynVoice* m_voice;
unsigned int m_currentTG;
};

View File

@@ -19,6 +19,6 @@
#if !defined(VERSION_H)
#define VERSION_H
const char* VERSION = "20200401";
const char* VERSION = "20200403";
#endif

View File

@@ -41,7 +41,7 @@ m_ambeFile(),
m_slot(slot),
m_lc(FLCO_GROUP, id, tg),
m_embeddedLC(),
m_status(VS_NONE),
m_status(XLXVS_NONE),
m_timer(1000U, 1U),
m_stopWatch(),
m_seqNo(0U),
@@ -68,7 +68,7 @@ CXLXVoice::~CXLXVoice()
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
for (std::unordered_map<std::string, CPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
for (std::unordered_map<std::string, CXLXPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
delete it->second;
m_data.clear();
@@ -115,7 +115,7 @@ bool CXLXVoice::open()
unsigned int start = ::atoi(p2) * AMBE_LENGTH;
unsigned int length = ::atoi(p3) * AMBE_LENGTH;
CPositions* pos = new CPositions;
CXLXPositions* pos = new CXLXPositions;
pos->m_start = start;
pos->m_length = length;
@@ -171,7 +171,7 @@ void CXLXVoice::createVoice(const std::vector<std::string>& words)
unsigned int ambeLength = 0U;
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
if (m_positions.count(*it) > 0U) {
CPositions* position = m_positions.at(*it);
CXLXPositions* position = m_positions.at(*it);
ambeLength += position->m_length;
} else {
LogWarning("Unable to find character/phrase \"%s\" in the index", (*it).c_str());
@@ -199,7 +199,7 @@ void CXLXVoice::createVoice(const std::vector<std::string>& words)
unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH;
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
if (m_positions.count(*it) > 0U) {
CPositions* position = m_positions.at(*it);
CXLXPositions* position = m_positions.at(*it);
unsigned int start = position->m_start;
unsigned int length = position->m_length;
::memcpy(ambeData + pos, m_ambe + start, length);
@@ -269,13 +269,13 @@ void CXLXVoice::createVoice(const std::vector<std::string>& words)
delete[] ambeData;
m_status = VS_WAITING;
m_status = XLXVS_WAITING;
m_timer.start();
}
bool CXLXVoice::read(CDMRData& data)
{
if (m_status != VS_SENDING)
if (m_status != XLXVS_SENDING)
return false;
unsigned int count = m_stopWatch.elapsed() / DMR_SLOT_TIME;
@@ -291,7 +291,7 @@ bool CXLXVoice::read(CDMRData& data)
delete *it;
m_data.clear();
m_timer.stop();
m_status = VS_NONE;
m_status = XLXVS_NONE;
}
return true;
@@ -304,9 +304,9 @@ void CXLXVoice::clock(unsigned int ms)
{
m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
if (m_status == VS_WAITING) {
if (m_status == XLXVS_WAITING) {
m_stopWatch.start();
m_status = VS_SENDING;
m_status = XLXVS_SENDING;
m_it = m_data.begin();
m_sent = 0U;
}

View File

@@ -29,13 +29,13 @@
#include <vector>
#include <unordered_map>
enum VOICE_STATUS {
VS_NONE,
VS_WAITING,
VS_SENDING
enum XLXVOICE_STATUS {
XLXVS_NONE,
XLXVS_WAITING,
XLXVS_SENDING
};
struct CPositions {
struct CXLXPositions {
unsigned int m_start;
unsigned int m_length;
};
@@ -60,14 +60,14 @@ private:
unsigned int m_slot;
CDMRLC m_lc;
CDMREmbeddedData m_embeddedLC;
VOICE_STATUS m_status;
XLXVOICE_STATUS m_status;
CTimer m_timer;
CStopWatch m_stopWatch;
unsigned int m_seqNo;
unsigned int m_streamId;
unsigned int m_sent;
unsigned char* m_ambe;
std::unordered_map<std::string, CPositions*> m_positions;
std::unordered_map<std::string, CXLXPositions*> m_positions;
std::vector<CDMRData*> m_data;
std::vector<CDMRData*>::const_iterator m_it;