244 lines
6.7 KiB
C++
Executable File
244 lines
6.7 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* RtState
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Christian Fröbel, NLE, 2018-12-16
|
|
*/
|
|
|
|
#include "rt_state.h"
|
|
#include <QString>
|
|
#include <QtGlobal>
|
|
#include <utility>
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
namespace AudioVideoManagement
|
|
{
|
|
|
|
|
|
namespace
|
|
{
|
|
int toIndex(AvaRtPos p)
|
|
{
|
|
return p - AvaRtPos::min();
|
|
}
|
|
} // anonymous namespace
|
|
|
|
|
|
RtState::Key RtState::Key::createFrom(const RtState::RadioCircuit &radioCircuit)
|
|
{
|
|
return {radioCircuit.radioSystem, radioCircuit.id};
|
|
}
|
|
|
|
bool RtState::Key::operator==(const RtState::Key &other) const
|
|
{
|
|
return std::make_pair(radioSystem, id) == std::make_pair(other.radioSystem, other.id);
|
|
}
|
|
|
|
bool RtState::Key::operator<(const Key &other) const
|
|
{
|
|
return std::make_pair(radioSystem, id) < std::make_pair(other.radioSystem, other.id);
|
|
}
|
|
|
|
void RtState::setRadioCircuits(const QVector<RadioCircuit> &radioCircuits)
|
|
{
|
|
std::map<Key, CircuitState> newCircuits;
|
|
for (const auto &radioCircuit: radioCircuits)
|
|
{
|
|
Q_ASSERT(!radioCircuit.name.empty());
|
|
|
|
// If we know the new radio circuit already, we keep the CircuitState.
|
|
const Key key = Key::createFrom(radioCircuit);
|
|
CircuitState state{radioCircuit.name}; // default
|
|
auto found = m_radioCircuits.find(key);
|
|
bool alreadyKnown = found != m_radioCircuits.end();
|
|
|
|
if (alreadyKnown)
|
|
{
|
|
// Use the known state; but in any case use the (possibly) new name.
|
|
state = found->second;
|
|
state.name = radioCircuit.name;
|
|
}
|
|
|
|
auto insertResult = newCircuits.insert(std::make_pair(key, state));
|
|
Q_ASSERT(insertResult.second);
|
|
}
|
|
m_radioCircuits = std::move(newCircuits);
|
|
|
|
|
|
std::array<PosState, AvaRtPos::count()> newStates;
|
|
const auto count = std::min(static_cast<int>(radioCircuits.size()), AvaRtPos::count());
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
const Key key = Key::createFrom(radioCircuits.at(i));
|
|
auto found = std::find_if(m_states.begin(), m_states.end(), [&key] (const PosState &s) { return s.key == key; });
|
|
bool isSelected = found != m_states.end();
|
|
|
|
if (isSelected)
|
|
newStates.at(i) = *found;
|
|
else
|
|
newStates.at(i) = PosState{key};
|
|
}
|
|
m_states = std::move(newStates);
|
|
}
|
|
|
|
void RtState::changeName(const RtState::RadioCircuit &radioCircuit)
|
|
{
|
|
Key key{radioCircuit.radioSystem, radioCircuit.id};
|
|
auto found = m_radioCircuits.find(key);
|
|
|
|
Q_ASSERT(found != m_radioCircuits.end());
|
|
if (found == m_radioCircuits.end())
|
|
{
|
|
qWarning() << "RtState::changeName: radio circuit not found!";
|
|
return;
|
|
}
|
|
|
|
found->second.name = radioCircuit.name;
|
|
}
|
|
|
|
void RtState::setSumChannel(AvaSumChannel sumChannel)
|
|
{
|
|
m_sumChannel = sumChannel;
|
|
}
|
|
|
|
void RtState::setSelection(AvaRtPos pos, const std::string &name, AvaRtButtonState s)
|
|
{
|
|
if (name.empty())
|
|
{
|
|
// The assertion does not always hold. AVS_Workstation may send us a button state
|
|
// other than AvaRtButtonState::None even when no radio circuit is selected.
|
|
// In that case we set the button state to AvaRtButtonState::None anyway.
|
|
// Fixed in AVS since Rev. 588.
|
|
Q_ASSERT(s == AvaRtButtonState::None);
|
|
m_states.at(toIndex(pos)) = PosState{};
|
|
return;
|
|
}
|
|
|
|
auto found = findRadioCircuit(name);
|
|
Q_ASSERT(found != m_radioCircuits.end());
|
|
|
|
if (found == m_radioCircuits.end())
|
|
{
|
|
qWarning() << "RtState::setSelection: radio circuit not found!";
|
|
return;
|
|
}
|
|
|
|
m_states.at(toIndex(pos)) = PosState{found->first, s};
|
|
}
|
|
|
|
void RtState::setVolume(const std::string &name, AvaVolume volume)
|
|
{
|
|
auto it = findRadioCircuit(name);
|
|
Q_ASSERT(it != m_radioCircuits.end());
|
|
|
|
if (it == m_radioCircuits.end())
|
|
{
|
|
qWarning() << "RtState::setVolume: radio circuit not found!";
|
|
return;
|
|
}
|
|
|
|
it->second.volume = volume;
|
|
}
|
|
|
|
std::string RtState::toCommand() const
|
|
{
|
|
std::ostringstream availableCircuits;
|
|
for (const auto &keyValue: m_radioCircuits)
|
|
availableCircuits << keyValue.second.toCommandPart() << ' ';
|
|
|
|
std::ostringstream selectedCircuits;
|
|
std::ostringstream states;
|
|
for (const auto &s: m_states)
|
|
{
|
|
selectedCircuits << s.toCommandSelectionPart(m_radioCircuits) << ' ';
|
|
states << s.toCommandStatePart() << ' ';
|
|
}
|
|
|
|
static const QString command = QStringLiteral(R"(setRtProfile "Default" "%1" "%2" "%3" %4)");
|
|
return command.arg(QString::fromStdString(availableCircuits.str()),
|
|
QString::fromStdString(selectedCircuits.str()),
|
|
QString::fromStdString(states.str()),
|
|
QString::number(static_cast<int>(m_sumChannel))).toStdString();
|
|
}
|
|
|
|
std::vector<std::string> RtState::allRadioCircuits() const
|
|
{
|
|
std::vector<std::string> allCircuits;
|
|
allCircuits.reserve(m_radioCircuits.size());
|
|
|
|
for (const auto &keyValue: m_radioCircuits)
|
|
allCircuits.push_back(keyValue.second.name);
|
|
|
|
return allCircuits;
|
|
}
|
|
|
|
std::vector<std::string> RtState::selectedRadioCircuits() const
|
|
{
|
|
std::vector<std::string> selectedCircuits;
|
|
selectedCircuits.reserve(m_states.size());
|
|
auto isFirstChannel = [](AvaSumChannel sc, AvaRtButtonState bs)
|
|
{
|
|
switch (sc)
|
|
{
|
|
case AvaSumChannel::Left:
|
|
return bs == AvaRtButtonState::Right;
|
|
case AvaSumChannel::Right:
|
|
return bs == AvaRtButtonState::Left;
|
|
};
|
|
return false;
|
|
};
|
|
for (const PosState &state: m_states)
|
|
{
|
|
if (state.key)
|
|
{
|
|
if (isFirstChannel(m_sumChannel, state.buttonState))
|
|
selectedCircuits.insert(selectedCircuits.begin(), m_radioCircuits.find(*state.key)->second.name);
|
|
else
|
|
selectedCircuits.push_back(m_radioCircuits.find(*state.key)->second.name);
|
|
}
|
|
}
|
|
|
|
return selectedCircuits;
|
|
}
|
|
|
|
std::map<RtState::Key, RtState::CircuitState>::iterator RtState::findRadioCircuit(const std::string &name)
|
|
{
|
|
auto withName = [&name] (const std::map<Key, CircuitState>::value_type &keyValue) { return keyValue.second.name == name; };
|
|
return std::find_if(m_radioCircuits.begin(), m_radioCircuits.end(), withName);
|
|
}
|
|
|
|
RtState::CircuitState::CircuitState(const std::string &name_):
|
|
name(name_)
|
|
{}
|
|
|
|
std::string RtState::CircuitState::toCommandPart() const
|
|
{
|
|
return QStringLiteral("15 %1 {%2}").arg(QString::number(static_cast<int>(volume)), QString::fromStdString(name)).toStdString();
|
|
}
|
|
|
|
RtState::PosState::PosState(const Key &key_, AvaRtButtonState s)
|
|
: key(key_)
|
|
, buttonState(s)
|
|
{}
|
|
|
|
std::string RtState::PosState::toCommandSelectionPart(const std::map<Key, CircuitState> &radioCircuits) const
|
|
{
|
|
std::string name;
|
|
if (key)
|
|
name = radioCircuits.find(*key)->second.name;
|
|
return QStringLiteral("{%1}").arg(QString::fromStdString(name)).toStdString();
|
|
}
|
|
|
|
std::string RtState::PosState::toCommandStatePart() const
|
|
{
|
|
return std::to_string(static_cast<int>(buttonState));
|
|
}
|
|
|
|
} // namespace AudioVideoManagement
|