/** * @RDE_HEADER@ * RtState * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, NLE, 2018-12-16 */ #include "rt_state.h" #include #include #include #include #include #include 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 &radioCircuits) { std::map 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 newStates; const auto count = std::min(static_cast(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(m_sumChannel))).toStdString(); } std::vector RtState::allRadioCircuits() const { std::vector allCircuits; allCircuits.reserve(m_radioCircuits.size()); for (const auto &keyValue: m_radioCircuits) allCircuits.push_back(keyValue.second.name); return allCircuits; } std::vector RtState::selectedRadioCircuits() const { std::vector 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::iterator RtState::findRadioCircuit(const std::string &name) { auto withName = [&name] (const std::map::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(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 &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(buttonState)); } } // namespace AudioVideoManagement