<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <validationinterface.h>

#include <primitives/block.h>
#include <scheduler.h>
#include <txmempool.h>
#include <util/system.h>
#include <validation.h>

#include <list>
#include <atomic>
#include <future>
#include <utility>

#include <boost/signals2/signal.hpp>

struct ValidationInterfaceConnections {
    boost::signals2::scoped_connection UpdatedBlockTip;
    boost::signals2::scoped_connection TransactionAddedToMempool;
    boost::signals2::scoped_connection BlockConnected;
    boost::signals2::scoped_connection BlockDisconnected;
    boost::signals2::scoped_connection TransactionRemovedFromMempool;
    boost::signals2::scoped_connection ChainStateFlushed;
    boost::signals2::scoped_connection Broadcast;
    boost::signals2::scoped_connection BlockChecked;
    boost::signals2::scoped_connection NewPoWValidBlock;
    boost::signals2::scoped_connection ProcessModuleMessage;
    boost::signals2::scoped_connection NotifyGovernanceObject;
    boost::signals2::scoped_connection NotifyGovernanceVote;
};

struct MainSignalsInstance {
    boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
    boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
    boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
    boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
    boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
    boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
    boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
    boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
    boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
    boost::signals2::signal<void (CNode*, const std::string&, CDataStream&, CConnman*)> ProcessModuleMessage;
    boost::signals2::signal<void (const CGovernanceObject&)> NotifyGovernanceObject;
    boost::signals2::signal<void (const CGovernanceVote&)> NotifyGovernanceVote;

    // We are not allowed to assume the scheduler only runs in one thread,
    // but must ensure all callbacks happen in-order, so we end up creating
    // our own queue here :(
    SingleThreadedSchedulerClient m_schedulerClient;
    std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;

    explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
};

static CMainSignals g_signals;

// This map has to a separate global instead of a member of MainSignalsInstance,
// because RegisterWithMempoolSignals is currently called before RegisterBackgroundSignalScheduler,
// so MainSignalsInstance hasn't been created yet.
static std::unordered_map<CTxMemPool*, boost::signals2::scoped_connection> g_connNotifyEntryRemoved;

void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
    assert(!m_internals);
    m_internals.reset(new MainSignalsInstance(&scheduler));
}

void CMainSignals::UnregisterBackgroundSignalScheduler() {
    m_internals.reset(nullptr);
}

void CMainSignals::FlushBackgroundCallbacks() {
    if (m_internals) {
        m_internals->m_schedulerClient.EmptyQueue();
    }
}

size_t CMainSignals::CallbacksPending() {
    if (!m_internals) return 0;
    return m_internals->m_schedulerClient.CallbacksPending();
}

void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) {
    g_connNotifyEntryRemoved.emplace(std::piecewise_construct,
        std::forward_as_tuple(&pool),
        std::forward_as_tuple(pool.NotifyEntryRemoved.connect(std::bind(&CMainSignals::MempoolEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)))
    );
}

void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) {
    g_connNotifyEntryRemoved.erase(&pool);
}

CMainSignals& GetMainSignals()
{
    return g_signals;
}

void RegisterValidationInterface(CValidationInterface* pwalletIn) {
    ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
    conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
    conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1));
    conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1));
    conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect(std::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, std::placeholders::_1));
    conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.NewPoWValidBlock = g_signals.m_internals->NewPoWValidBlock.connect(std::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.ProcessModuleMessage = g_signals.m_internals->ProcessModuleMessage.connect(std::bind(&CValidationInterface::ProcessModuleMessage, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
    conns.NotifyGovernanceObject = g_signals.m_internals->NotifyGovernanceObject.connect(std::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, std::placeholders::_1));
    conns.NotifyGovernanceVote = g_signals.m_internals->NotifyGovernanceVote.connect(std::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, std::placeholders::_1));
}

void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
    g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
}

void UnregisterAllValidationInterfaces() {
    if (!g_signals.m_internals) {
        return;
    }
    g_signals.m_internals->m_connMainSignals.clear();
}

void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
    g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
}

void SyncWithValidationInterfaceQueue() {
    AssertLockNotHeld(cs_main);
    // Block until the validation queue drains
    std::promise<void> promise;
    CallFunctionInValidationInterfaceQueue([&promise] {
        promise.set_value();
    });
    promise.get_future().wait();
}

void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) {
    if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) {
        m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
            m_internals->TransactionRemovedFromMempool(ptx);
        });
    }
}

void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
    // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
    // the chain actually updates. One way to ensure this is for the caller to invoke this signal
    // in the same critical section where the chain is updated

    m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, fInitialDownload, this] {
        m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
    });
}

void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
    m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
        m_internals->TransactionAddedToMempool(ptx);
    });
}

void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) {
    m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] {
        m_internals->BlockConnected(pblock, pindex, *pvtxConflicted);
    });
}

void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) {
    m_internals->m_schedulerClient.AddToProcessQueue([pblock, this] {
        m_internals->BlockDisconnected(pblock);
    });
}

void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
    m_internals->m_schedulerClient.AddToProcessQueue([locator, this] {
        m_internals->ChainStateFlushed(locator);
    });
}

void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
    m_internals->Broadcast(nBestBlockTime, connman);
}

void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
    m_internals->BlockChecked(block, state);
}

void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
    m_internals->NewPoWValidBlock(pindex, block);
}

void CMainSignals::ProcessModuleMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman* connman) {
    m_internals->ProcessModuleMessage(pfrom, strCommand, vRecv, connman);
}

void CMainSignals::NotifyGovernanceObject(const CGovernanceObject &gobject) {
    m_internals->NotifyGovernanceObject(gobject);
}

void CMainSignals::NotifyGovernanceVote(const CGovernanceVote &govote) {
    m_internals->NotifyGovernanceVote(govote);
}
<commit_msg>Check m_internals in UnregisterValidationInterface<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <validationinterface.h>

#include <primitives/block.h>
#include <scheduler.h>
#include <txmempool.h>
#include <util/system.h>
#include <validation.h>

#include <list>
#include <atomic>
#include <future>
#include <utility>

#include <boost/signals2/signal.hpp>

struct ValidationInterfaceConnections {
    boost::signals2::scoped_connection UpdatedBlockTip;
    boost::signals2::scoped_connection TransactionAddedToMempool;
    boost::signals2::scoped_connection BlockConnected;
    boost::signals2::scoped_connection BlockDisconnected;
    boost::signals2::scoped_connection TransactionRemovedFromMempool;
    boost::signals2::scoped_connection ChainStateFlushed;
    boost::signals2::scoped_connection Broadcast;
    boost::signals2::scoped_connection BlockChecked;
    boost::signals2::scoped_connection NewPoWValidBlock;
    boost::signals2::scoped_connection ProcessModuleMessage;
    boost::signals2::scoped_connection NotifyGovernanceObject;
    boost::signals2::scoped_connection NotifyGovernanceVote;
};

struct MainSignalsInstance {
    boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
    boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
    boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
    boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
    boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
    boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
    boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
    boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
    boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
    boost::signals2::signal<void (CNode*, const std::string&, CDataStream&, CConnman*)> ProcessModuleMessage;
    boost::signals2::signal<void (const CGovernanceObject&)> NotifyGovernanceObject;
    boost::signals2::signal<void (const CGovernanceVote&)> NotifyGovernanceVote;

    // We are not allowed to assume the scheduler only runs in one thread,
    // but must ensure all callbacks happen in-order, so we end up creating
    // our own queue here :(
    SingleThreadedSchedulerClient m_schedulerClient;
    std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;

    explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
};

static CMainSignals g_signals;

// This map has to a separate global instead of a member of MainSignalsInstance,
// because RegisterWithMempoolSignals is currently called before RegisterBackgroundSignalScheduler,
// so MainSignalsInstance hasn't been created yet.
static std::unordered_map<CTxMemPool*, boost::signals2::scoped_connection> g_connNotifyEntryRemoved;

void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
    assert(!m_internals);
    m_internals.reset(new MainSignalsInstance(&scheduler));
}

void CMainSignals::UnregisterBackgroundSignalScheduler() {
    m_internals.reset(nullptr);
}

void CMainSignals::FlushBackgroundCallbacks() {
    if (m_internals) {
        m_internals->m_schedulerClient.EmptyQueue();
    }
}

size_t CMainSignals::CallbacksPending() {
    if (!m_internals) return 0;
    return m_internals->m_schedulerClient.CallbacksPending();
}

void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) {
    g_connNotifyEntryRemoved.emplace(std::piecewise_construct,
        std::forward_as_tuple(&pool),
        std::forward_as_tuple(pool.NotifyEntryRemoved.connect(std::bind(&CMainSignals::MempoolEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)))
    );
}

void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) {
    g_connNotifyEntryRemoved.erase(&pool);
}

CMainSignals& GetMainSignals()
{
    return g_signals;
}

void RegisterValidationInterface(CValidationInterface* pwalletIn) {
    ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
    conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
    conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1));
    conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1));
    conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect(std::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, std::placeholders::_1));
    conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.NewPoWValidBlock = g_signals.m_internals->NewPoWValidBlock.connect(std::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.ProcessModuleMessage = g_signals.m_internals->ProcessModuleMessage.connect(std::bind(&CValidationInterface::ProcessModuleMessage, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
    conns.NotifyGovernanceObject = g_signals.m_internals->NotifyGovernanceObject.connect(std::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, std::placeholders::_1));
    conns.NotifyGovernanceVote = g_signals.m_internals->NotifyGovernanceVote.connect(std::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, std::placeholders::_1));
}

void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
    if (g_signals.m_internals) {
        g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
    }
}

void UnregisterAllValidationInterfaces() {
    if (!g_signals.m_internals) {
        return;
    }
    g_signals.m_internals->m_connMainSignals.clear();
}

void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
    g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
}

void SyncWithValidationInterfaceQueue() {
    AssertLockNotHeld(cs_main);
    // Block until the validation queue drains
    std::promise<void> promise;
    CallFunctionInValidationInterfaceQueue([&promise] {
        promise.set_value();
    });
    promise.get_future().wait();
}

void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) {
    if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) {
        m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
            m_internals->TransactionRemovedFromMempool(ptx);
        });
    }
}

void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
    // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
    // the chain actually updates. One way to ensure this is for the caller to invoke this signal
    // in the same critical section where the chain is updated

    m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, fInitialDownload, this] {
        m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
    });
}

void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
    m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
        m_internals->TransactionAddedToMempool(ptx);
    });
}

void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) {
    m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] {
        m_internals->BlockConnected(pblock, pindex, *pvtxConflicted);
    });
}

void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) {
    m_internals->m_schedulerClient.AddToProcessQueue([pblock, this] {
        m_internals->BlockDisconnected(pblock);
    });
}

void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
    m_internals->m_schedulerClient.AddToProcessQueue([locator, this] {
        m_internals->ChainStateFlushed(locator);
    });
}

void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
    m_internals->Broadcast(nBestBlockTime, connman);
}

void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
    m_internals->BlockChecked(block, state);
}

void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
    m_internals->NewPoWValidBlock(pindex, block);
}

void CMainSignals::ProcessModuleMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman* connman) {
    m_internals->ProcessModuleMessage(pfrom, strCommand, vRecv, connman);
}

void CMainSignals::NotifyGovernanceObject(const CGovernanceObject &gobject) {
    m_internals->NotifyGovernanceObject(gobject);
}

void CMainSignals::NotifyGovernanceVote(const CGovernanceVote &govote) {
    m_internals->NotifyGovernanceVote(govote);
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_extract_sbe_rc.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_extract_sbe_rc.H
///
/// @brief Check for errors on the SBE, OTPROM, PIBMEM & SEEPROM
//------------------------------------------------------------------------------
// *HWP HW Owner        : Soma BhanuTej <soma.bhanu@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil Kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 3
// *HWP Consumed by     : FSP:HB
//------------------------------------------------------------------------------

#ifndef _P9_EXTRACT_SBE_RC_H_
#define _P9_EXTRACT_SBE_RC_H_

#include <fapi2.H>

namespace P9_EXTRACT_SBE_RC
{
enum RETURN_ACTION
{
    ERROR_RECOVERED    = 0, // Something happened with the SBE, we committed the errors involved
    // (as informational), attempted and successfully rebooted the SBE
    RESTART_SBE        = 1, // Trigger external HRESET to reset SBE
    RESTART_CBS        = 2, // Trigger Warm ipl where we don't switch off VSB just toggle start_cbs from FSP
    REIPL_BKP_SEEPROM  = 3, // Run IPL by selecting backup seeprom
    REIPL_UPD_SEEPROM  = 4, // Reload/update of SEEPROM required or deconfig the chip
    NO_RECOVERY_ACTION = 5, // No recovery action possible to correct this error
};
};

typedef fapi2::ReturnCode (*p9_extract_sbe_rc_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&,
        P9_EXTRACT_SBE_RC::RETURN_ACTION&, bool, bool);

/// @brief called on all chips(master and slaves) to look for any correctable errors on the SBE, OTPROM, PIBMEM & SEEPROM, the soft_error flag tells the procedure not to generate error if no HW issue.
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PROC_CHIP target
/// @param[out]    o_return_action    Returns the action to be taken on an error
/// @param[in]     i_set_sdb          To program the chip to set SDB
/// @param[in]     i_unsecure_mode    To get debug info in a unsecure mode
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_extract_sbe_rc(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip,
                                        P9_EXTRACT_SBE_RC::RETURN_ACTION& o_return_action,
                                        bool i_set_sdb = false,
                                        bool i_unsecure_mode = false);
}

#endif
<commit_msg>Additional checks to p9_extract_sbe_rc<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_extract_sbe_rc.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_extract_sbe_rc.H
///
/// @brief Check for errors on the SBE, OTPROM, PIBMEM & SEEPROM
//------------------------------------------------------------------------------
// *HWP HW Owner        : Soma BhanuTej <soma.bhanu@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil Kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 3
// *HWP Consumed by     : FSP:HB
//------------------------------------------------------------------------------

#ifndef _P9_EXTRACT_SBE_RC_H_
#define _P9_EXTRACT_SBE_RC_H_
#define btos(x) ((x)?"TRUE":"FALSE")

#include <fapi2.H>

namespace P9_EXTRACT_SBE_RC
{
enum RETURN_ACTION
{
    ERROR_RECOVERED    = 0, // Something happened with the SBE, we committed the errors involved
    // (as informational), attempted and successfully rebooted the SBE
    RESTART_SBE        = 1, // Trigger external HRESET to reset SBE
    RESTART_CBS        = 2, // Trigger Warm ipl where we don't switch off VSB just toggle start_cbs from FSP
    REIPL_BKP_SEEPROM  = 3, // Run IPL by selecting backup seeprom
    REIPL_UPD_SEEPROM  = 4, // Reload/update of SEEPROM required or deconfig the chip
    NO_RECOVERY_ACTION = 5, // No recovery action possible to correct this error
};
};

typedef fapi2::ReturnCode (*p9_extract_sbe_rc_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&,
        P9_EXTRACT_SBE_RC::RETURN_ACTION&, bool, bool);

/// @brief called on all chips(master and slaves) to look for any correctable errors on the SBE, OTPROM, PIBMEM & SEEPROM, the soft_error flag tells the procedure not to generate error if no HW issue.
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PROC_CHIP target
/// @param[out]    o_return_action    Returns the action to be taken on an error
/// @param[in]     i_set_sdb          To program the chip to set SDB
/// @param[in]     i_unsecure_mode    To get debug info in a unsecure mode
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_extract_sbe_rc(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip,
                                        P9_EXTRACT_SBE_RC::RETURN_ACTION& o_return_action,
                                        bool i_set_sdb = false,
                                        bool i_unsecure_mode = false);
}

#endif
<|endoftext|>


<commit_before>#include "WindowViewer.h"
#include <unordered_map>
#include "renderer/Camera.h"
#include "renderer/ToonMapper.h"
#include "renderer/Renderer.h"

#include <iostream>
#include <Windows.h>

using namespace std;

namespace {
  wstring widen(const std::string &src) {
	  wchar_t *wcs = new wchar_t[src.length() + 1];
    size_t converted;
    mbstowcs_s(&converted, wcs, src.length()+1, src.c_str(), src.length());
	  wstring dest = wcs;
	  delete [] wcs;
    return dest;
  }
}

namespace OmochiRenderer {
  class WindowViewer::WindowImpl {
    WindowViewer &viewer;
    static unordered_map<size_t, WindowImpl *> handleToInstance;

    wstring wstr_title;
    HWND m_hWnd;
    size_t m_timerID;

  public:
    explicit WindowImpl(WindowViewer &viewer_)
      : viewer(viewer_)
      , wstr_title()
      , m_hWnd(NULL)
      , m_timerID(0)
    {
    }

    bool CreateNewWindow() {
      HWND hWnd = CreateNewWindow_impl();
      m_hWnd = hWnd;
      if (hWnd != INVALID_HANDLE_VALUE) {
        RegisterWindow(hWnd, this);
        ResetTimer();
        return true;
      }
      return false;
    }

    void ResetTimer() {
      if (viewer.m_refreshTimeInMsec < 2) return;
      if (m_timerID != 0) {
        KillTimer(m_hWnd, m_timerID);
      }
      m_timerID = WM_USER + rand() % 10000;
      SetTimer(m_hWnd, m_timerID, viewer.m_refreshTimeInMsec - 1, NULL);
    }

    static void MessageLoop() {
      // bZ[W[v
      MSG msg;
	    while(true)
	    {
		    BOOL ret = GetMessage( &msg, NULL, 0, 0 );  // bZ[W擾
		    if( ret == 0 || ret == -1 )
		    {
			    // AvP[VI郁bZ[WĂA
			    // 邢 GetMessage() s( -1 Ԃꂽ jA[v𔲂
			    break;
		    }
		    else
		    {
			    // bZ[W
			    TranslateMessage( &msg );
			    DispatchMessage( &msg );
		    }
	    }

    }

  private:
    HWND CreateNewWindow_impl() {
      WNDCLASSEX wc;
      HWND hWnd;
      HINSTANCE hInst = static_cast<HINSTANCE>(GetModuleHandle(NULL));

      wstr_title = widen(viewer.m_windowTitle.c_str());

      // EBhENX̏ݒ
      wc.cbSize = sizeof(wc);               // \̃TCY
      wc.style = CS_HREDRAW | CS_VREDRAW;   // X^C
      wc.lpfnWndProc = WindowImpl::WndProc;             // EBhEvV[W
      wc.cbClsExtra = 0;                    // gP
      wc.cbWndExtra = 0;                    // gQ
      wc.hInstance = hInst;                 // CX^Xnh
      wc.hIcon = (HICON)LoadImage(          // ACR
	      NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
	      0, 0, LR_DEFAULTSIZE | LR_SHARED
      );
      wc.hIconSm = wc.hIcon;                // qACR
      wc.hCursor = (HCURSOR)LoadImage(      // }EXJ[\
	      NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
	      0, 0, LR_DEFAULTSIZE | LR_SHARED
      );
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // EBhEwi
      wc.lpszMenuName = NULL;                     // j[
      // ugly code
      wc.lpszClassName = wstr_title.c_str();// EBhENX

      // EBhENXo^
      if( RegisterClassEx( &wc ) == 0 ){ return (HWND)INVALID_HANDLE_VALUE; }

      int width = viewer.m_camera.GetScreenWidth();
      int height = viewer.m_camera.GetScreenHeight();

      int x = ( GetSystemMetrics( SM_CXSCREEN ) - width ) / 2;
      int y = ( GetSystemMetrics( SM_CYSCREEN ) - height ) / 2;

      // EBhE쐬
      hWnd = CreateWindow(
	      wc.lpszClassName,      // EBhENX
        wstr_title.c_str(),  // ^Cgo[ɕ\镶
	      WS_OVERLAPPEDWINDOW,   // EBhE̎
	      x,         // EBhE\ʒuiXWj
	      y,         // EBhE\ʒuiYWj
	      width,         // EBhE̕
	      height,         // EBhE̍
	      NULL,                  // eEBhẼEBhEnh
	      NULL,                  // j[nh
	      hInst,                 // CX^Xnh
	      NULL                   // ̑̍쐬f[^
      );

      if (hWnd == 0 || hWnd == INVALID_HANDLE_VALUE) return (HWND)INVALID_HANDLE_VALUE;

      RECT wrect, crect;
      GetWindowRect(hWnd, &wrect); GetClientRect(hWnd, &crect);
      int truewidth = width + (wrect.right-wrect.left) - (crect.right-crect.left);
      int trueheight = height + (wrect.bottom-wrect.top) - (crect.bottom-crect.top);
      x = (GetSystemMetrics(SM_CXSCREEN) - truewidth)/2;
      y = (GetSystemMetrics(SM_CYSCREEN) - trueheight)/2;
      MoveWindow(hWnd, x, y, truewidth, trueheight, TRUE);

      // EBhE\
	    ShowWindow( hWnd, SW_SHOW );
	    UpdateWindow( hWnd );

      cerr << "HWND = " << hWnd << endl;

      return hWnd;
    }

    static void RegisterWindow(HWND hWnd, WindowImpl *instance) {
      size_t sizethWnd = reinterpret_cast<size_t>(hWnd);
      handleToInstance[sizethWnd] = instance;
    }

    static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
      size_t sizethWnd = reinterpret_cast<size_t>(hWnd);
      if (handleToInstance.find(sizethWnd) == handleToInstance.end()) {
        return DefWindowProc( hWnd, msg, wp, lp );
      }

      return handleToInstance[sizethWnd]->WndProc_impl(hWnd, msg, wp, lp);
      //return WndProc_impl(hWnd, msg, wp, lp);
    }

  private:
    LRESULT WndProc_impl(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
      switch (msg) {
      case WM_CREATE:
        cerr << "WM_CREATE = " << hWnd << endl;
        InvalidateRect(hWnd, NULL, TRUE);
        break;

      case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;

      case WM_PAINT:
        {
          PAINTSTRUCT paint;
          HDC hdc = BeginPaint(hWnd, &paint);

          int width = viewer.m_camera.GetScreenWidth();
          int height = viewer.m_camera.GetScreenHeight();

          const Color *result = viewer.m_renderer.GetResult();
          for (int y=0; y<height; y++) {
            for (int x=0; x<width; x++) {
              int index = x+y*width;

              SetPixel(hdc,x,y,
                RGB(viewer.m_mapper.Map(result[index].x),
                  viewer.m_mapper.Map(result[index].y),
                  viewer.m_mapper.Map(result[index].z)
                ));
            }
          }

          // draw information
          //SetBkMode(hdc, TRANSPARENT);
          wstring info = widen(viewer.m_renderer.GetCurrentRenderingInfo());
          RECT rc; GetClientRect(hWnd, &rc);
          DrawText(hdc, info.c_str(), -1, &rc, DT_LEFT|DT_WORDBREAK);

          EndPaint(hWnd, &paint);
        }
        return 0;

      case WM_TIMER:
        if (static_cast<size_t>(wp) == m_timerID) {
          InvalidateRect(hWnd, NULL, FALSE);
        }
        break;
      }

      return DefWindowProc( hWnd, msg, wp, lp );
    }
  };

  unordered_map<size_t, WindowViewer::WindowImpl *> WindowViewer::WindowImpl::handleToInstance;

  WindowViewer::WindowViewer(
    const std::string &windowTitle,
    const Camera &camera,
    const PathTracer &renderer,
    const ToonMapper &mapper,
    const size_t refreshSpanInMsec)
    : m_windowTitle(windowTitle)
    , m_camera(camera)
    , m_renderer(renderer)
    , m_mapper(mapper)
    , m_pWindow(NULL)
    , m_windowThread()
    , m_callbackWhenClosed()
    , m_refreshTimeInMsec(refreshSpanInMsec)
  {
  }
  WindowViewer::~WindowViewer() {
  }

  void WindowViewer::StartViewerOnThisThread() {
    m_pWindow.reset(new WindowImpl(*this));
    m_pWindow->CreateNewWindow();

    WindowImpl::MessageLoop();

    if (m_callbackWhenClosed) {
      m_callbackWhenClosed();
    }
  }

  void WindowViewer::StartViewerOnNewThread() {
    m_windowThread.reset(new std::thread(
      [this]{
        m_pWindow.reset(new WindowImpl(*this));
        m_pWindow->CreateNewWindow();
        WindowImpl::MessageLoop();
        if (m_callbackWhenClosed) {
          m_callbackWhenClosed();
        }
    }
    ));
  }

  void WindowViewer::WaitWindowFinish() {
    if (m_windowThread) {
      m_windowThread->join();
      m_windowThread.reset();
    }
  }
}
<commit_msg>add OpenGL init code (no glut)<commit_after>#include "WindowViewer.h"
#include <unordered_map>
#include "renderer/Camera.h"
#include "renderer/ToonMapper.h"
#include "renderer/Renderer.h"

#include <iostream>
#include <Windows.h>

using namespace std;

#include "glew.h"
#include "glext.h"
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")

namespace {
  wstring widen(const std::string &src) {
	  wchar_t *wcs = new wchar_t[src.length() + 1];
    size_t converted;
    mbstowcs_s(&converted, wcs, src.length()+1, src.c_str(), src.length());
	  wstring dest = wcs;
	  delete [] wcs;
    return dest;
  }
}

namespace OmochiRenderer {
  class WindowViewer::WindowImpl {
    WindowViewer &viewer;
    static unordered_map<size_t, WindowImpl *> handleToInstance;

    wstring wstr_title;
    HWND m_hWnd;
    size_t m_timerID;
    HGLRC m_glrc;

  public:
    explicit WindowImpl(WindowViewer &viewer_)
      : viewer(viewer_)
      , wstr_title()
      , m_hWnd(NULL)
      , m_timerID(0)
      , m_glrc(NULL)
    {
    }
    ~WindowImpl()
    {
      if (m_glrc != NULL) wglDeleteContext(m_glrc);
    }

    bool CreateNewWindow() {
      HWND hWnd = CreateNewWindow_impl();
      if (hWnd != INVALID_HANDLE_VALUE) {
        RegisterWindow(hWnd, this);
        InitOpenGL(hWnd);
        //ResetTimer();
        return true;
      }
      return false;
    }

    void ResetTimer() {
      if (viewer.m_refreshTimeInMsec < 2) return;
      if (m_timerID != 0) {
        KillTimer(m_hWnd, m_timerID);
      }
      m_timerID = WM_USER + rand() % 10000;
      SetTimer(m_hWnd, m_timerID, viewer.m_refreshTimeInMsec - 1, NULL);
    }

    static void MessageLoop() {

      // bZ[W[v
      MSG msg;
	    while(true)
	    {
		    BOOL ret = GetMessage( &msg, NULL, 0, 0 );  // bZ[W擾
		    if( ret == 0 || ret == -1 )
		    {
			    // AvP[VI郁bZ[WĂA
			    // 邢 GetMessage() s( -1 Ԃꂽ jA[v𔲂
			    break;
		    }
		    else
		    {
			    // bZ[W
			    TranslateMessage( &msg );
			    DispatchMessage( &msg );
		    }
	    }

    }

  private:
    HWND CreateNewWindow_impl() {

      WNDCLASSEX wc;
      HWND hWnd;
      HINSTANCE hInst = static_cast<HINSTANCE>(GetModuleHandle(NULL));

      wstr_title = widen(viewer.m_windowTitle.c_str());

      // EBhENX̏ݒ
      wc.cbSize = sizeof(wc);               // \̃TCY
      wc.style = CS_HREDRAW | CS_VREDRAW;   // X^C
      wc.lpfnWndProc = WindowImpl::WndProc;             // EBhEvV[W
      wc.cbClsExtra = 0;                    // gP
      wc.cbWndExtra = 0;                    // gQ
      wc.hInstance = hInst;                 // CX^Xnh
      wc.hIcon = (HICON)LoadImage(          // ACR
	      NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
	      0, 0, LR_DEFAULTSIZE | LR_SHARED
      );
      wc.hIconSm = wc.hIcon;                // qACR
      wc.hCursor = (HCURSOR)LoadImage(      // }EXJ[\
	      NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
	      0, 0, LR_DEFAULTSIZE | LR_SHARED
      );
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // EBhEwi
      wc.lpszMenuName = NULL;                     // j[
      // ugly code
      wc.lpszClassName = wstr_title.c_str();// EBhENX

      // EBhENXo^
      if( RegisterClassEx( &wc ) == 0 ){ return (HWND)INVALID_HANDLE_VALUE; }

      int width = viewer.m_camera.GetScreenWidth();
      int height = viewer.m_camera.GetScreenHeight();

      int x = ( GetSystemMetrics( SM_CXSCREEN ) - width ) / 2;
      int y = ( GetSystemMetrics( SM_CYSCREEN ) - height ) / 2;

      // EBhE쐬
      hWnd = CreateWindow(
	      wc.lpszClassName,      // EBhENX
        wstr_title.c_str(),  // ^Cgo[ɕ\镶
	      WS_OVERLAPPEDWINDOW,   // EBhE̎
	      x,         // EBhE\ʒuiXWj
	      y,         // EBhE\ʒuiYWj
	      width,         // EBhE̕
	      height,         // EBhE̍
	      NULL,                  // eEBhẼEBhEnh
	      NULL,                  // j[nh
	      hInst,                 // CX^Xnh
	      NULL                   // ̑̍쐬f[^
      );

      if (hWnd == 0 || hWnd == INVALID_HANDLE_VALUE) return (HWND)INVALID_HANDLE_VALUE;

      RECT wrect, crect;
      GetWindowRect(hWnd, &wrect); GetClientRect(hWnd, &crect);
      int truewidth = width + (wrect.right-wrect.left) - (crect.right-crect.left);
      int trueheight = height + (wrect.bottom-wrect.top) - (crect.bottom-crect.top);
      x = (GetSystemMetrics(SM_CXSCREEN) - truewidth)/2;
      y = (GetSystemMetrics(SM_CYSCREEN) - trueheight)/2;
      MoveWindow(hWnd, x, y, truewidth, trueheight, TRUE);

      // EBhE\
	    ShowWindow( hWnd, SW_SHOW );
	    UpdateWindow( hWnd );

      cerr << "HWND = " << hWnd << endl;

      return hWnd;
    }

    static void RegisterWindow(HWND hWnd, WindowImpl *instance) {
      size_t sizethWnd = reinterpret_cast<size_t>(hWnd);
      handleToInstance[sizethWnd] = instance;
    }

    void InitOpenGL(HWND hWnd) {
      HDC hdc = GetDC(hWnd);

      try {
        // sNZtH[}bg̐ݒ
        PIXELFORMATDESCRIPTOR pdf = {
          sizeof(PIXELFORMATDESCRIPTOR),
          1, // version
          PFD_DRAW_TO_WINDOW |
          PFD_SUPPORT_OPENGL |
          PFD_DOUBLEBUFFER,
          24,
          0, 0, 0, 0, 0, 0,
          0,
          0,
          0,
          0, 0, 0, 0,
          32,
          0,
          0,
          PFD_MAIN_PLANE,
          0,
          0, 0, 0
        };
        int format = ChoosePixelFormat(hdc, &pdf);
        if (format == 0) throw "";

        if (!SetPixelFormat(hdc, format, &pdf)) throw "";

        // _OReLXg쐬
        m_glrc = wglCreateContext(hdc);
      }
      catch (...) {
        ReleaseDC(hWnd, hdc);
        return;
      }

      wglMakeCurrent(hdc, m_glrc);
      wglMakeCurrent(hdc, 0);
      ReleaseDC(hWnd, hdc);
      SendMessage(hWnd, WM_PAINT, NULL, NULL);
    }

    static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
      size_t sizethWnd = reinterpret_cast<size_t>(hWnd);
      if (handleToInstance.find(sizethWnd) == handleToInstance.end()) {
        return DefWindowProc( hWnd, msg, wp, lp );
      }

      return handleToInstance[sizethWnd]->WndProc_impl(hWnd, msg, wp, lp);
      //return WndProc_impl(hWnd, msg, wp, lp);
    }

  private:
    LRESULT WndProc_impl(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
      switch (msg) {
      case WM_CREATE:
        cerr << "WM_CREATE = " << hWnd << endl;
        InvalidateRect(hWnd, NULL, TRUE);
        break;

      case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;

      case WM_PAINT:
        {
          PAINTSTRUCT paint;
          HDC hdc = BeginPaint(hWnd, &paint);
          wglMakeCurrent(hdc, m_glrc);
          Render(hdc, hWnd);
          wglMakeCurrent(hdc, NULL);
          EndPaint(hWnd, &paint);
        }
        return 0;

      case WM_TIMER:
        if (static_cast<size_t>(wp) == m_timerID) {
          InvalidateRect(hWnd, NULL, FALSE);
        }
        break;
      }

      return DefWindowProc( hWnd, msg, wp, lp );
    }

    void Render(HDC hdc, HWND hWnd) {
      glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
      glClearDepth(1.0f);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      SwapBuffers(hdc);
      /*
      int width = viewer.m_camera.GetScreenWidth();
      int height = viewer.m_camera.GetScreenHeight();

      const Color *result = viewer.m_renderer.GetResult();
      for (int y = 0; y<height; y++) {
        for (int x = 0; x<width; x++) {
          int index = x + y*width;

          SetPixel(hdc, x, y,
            RGB(viewer.m_mapper.Map(result[index].x),
            viewer.m_mapper.Map(result[index].y),
            viewer.m_mapper.Map(result[index].z)
            ));
        }
      }

      // draw information
      //SetBkMode(hdc, TRANSPARENT);
      wstring info = widen(viewer.m_renderer.GetCurrentRenderingInfo());
      RECT rc; GetClientRect(hWnd, &rc);
      DrawText(hdc, info.c_str(), -1, &rc, DT_LEFT | DT_WORDBREAK);
      */
    }
  };

  unordered_map<size_t, WindowViewer::WindowImpl *> WindowViewer::WindowImpl::handleToInstance;

  WindowViewer::WindowViewer(
    const std::string &windowTitle,
    const Camera &camera,
    const PathTracer &renderer,
    const ToonMapper &mapper,
    const size_t refreshSpanInMsec)
    : m_windowTitle(windowTitle)
    , m_camera(camera)
    , m_renderer(renderer)
    , m_mapper(mapper)
    , m_pWindow(NULL)
    , m_windowThread()
    , m_callbackWhenClosed()
    , m_refreshTimeInMsec(refreshSpanInMsec)
  {
  }
  WindowViewer::~WindowViewer() {
  }

  void WindowViewer::StartViewerOnThisThread() {
    m_pWindow.reset(new WindowImpl(*this));
    m_pWindow->CreateNewWindow();

    WindowImpl::MessageLoop();

    if (m_callbackWhenClosed) {
      m_callbackWhenClosed();
    }
  }

  void WindowViewer::StartViewerOnNewThread() {
    m_windowThread.reset(new std::thread(
      [this]{
        m_pWindow.reset(new WindowImpl(*this));
        m_pWindow->CreateNewWindow();
        WindowImpl::MessageLoop();
        if (m_callbackWhenClosed) {
          m_callbackWhenClosed();
        }
    }
    ));
  }

  void WindowViewer::WaitWindowFinish() {
    if (m_windowThread) {
      m_windowThread->join();
      m_windowThread.reset();
    }
  }
}
<|endoftext|>


<commit_before>#include "drawer.hpp"
#include "proto_to_styles.hpp"
#include "feature_styler.hpp"

#include "../std/bind.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/scales.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/resource_manager.hpp"
#include "../graphics/straight_text_element.hpp"

#include "../indexer/drules_include.hpp"
#include "../indexer/feature.hpp"

#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/buffer_vector.hpp"

Drawer::Params::Params()
  : m_visualScale(1)
{
}

Drawer::Drawer(Params const & params)
  : m_visualScale(params.m_visualScale)
{
  m_pScreen.reset(new graphics::Screen(params));

  for (unsigned i = 0; i < m_pScreen->pipelinesCount(); ++i)
    m_pScreen->addClearPageFn(i, bind(&Drawer::ClearResourceCache, ThreadSlot(), i), 0);
}

namespace
{
  struct DoMakeInvalidRule
  {
    size_t m_threadSlot;
    uint32_t m_pipelineIDMask;

    DoMakeInvalidRule(size_t threadSlot, uint8_t pipelineID)
      : m_threadSlot(threadSlot), m_pipelineIDMask(pipelineID << 24)
    {}

    void operator() (int, int, int, drule::BaseRule * p)
    {
      if ((p->GetID(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID(m_threadSlot);
      if ((p->GetID2(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID2(m_threadSlot);
    }
  };
}

void Drawer::ClearResourceCache(size_t threadSlot, uint8_t pipelineID)
{
  drule::rules().ForEachRule(DoMakeInvalidRule(threadSlot, pipelineID));
}

void Drawer::beginFrame()
{
  m_pScreen->beginFrame();
}

void Drawer::endFrame()
{
  m_pScreen->endFrame();
}

void Drawer::clear(graphics::Color const & c, bool clearRT, float depth, bool clearDepth)
{
  m_pScreen->clear(c, clearRT, depth, clearDepth);
}

void Drawer::onSize(int w, int h)
{
  m_pScreen->onSize(w, h);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        string const & symbolName,
                        graphics::EPosition pos,
                        double depth)
{
  m_pScreen->drawSymbol(pt, symbolName, pos, depth);
}

void Drawer::drawCircle(m2::PointD const & pt,
                        graphics::EPosition pos,
                        di::DrawRule const & rule,
                        di::FeatureInfo::FeatureID const & id)
{
  graphics::Circle::Info ci;
  ConvertStyle(rule.m_rule->GetCircle(), m_visualScale, ci);

  graphics::CircleElement::Params params;

  params.m_depth = rule.m_depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_ci = ci;
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawCircle(params);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        graphics::EPosition pos,
                        di::DrawRule const & rule,
                        di::FeatureInfo::FeatureID const & id)
{
  graphics::Icon::Info info;
  ConvertStyle(rule.m_rule->GetSymbol(), info);

  graphics::SymbolElement::Params params;
  params.m_depth = rule.m_depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_info = info;
  params.m_renderer = m_pScreen.get();
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawSymbol(params);
}

void Drawer::drawPath(di::PathInfo const & path, di::DrawRule const * rules, size_t count)
{
  // if any rule needs caching - cache as a whole vector
  bool flag = false;
  for (size_t i = 0; i < count; ++i)
  {
    if (rules[i].GetID(m_pScreen->threadSlot()) == drule::BaseRule::empty_id)
    {
      flag = true;
      break;
    }
  }

  buffer_vector<graphics::Pen::Info, 8> penInfos(count);
  buffer_vector<graphics::Resource::Info const*, 8> infos(count);
  buffer_vector<uint32_t, 8> resIDs(count);

  if (flag)
  {
    // collect graphics::PenInfo into array and pack them as a whole
    for (size_t i = 0; i < count; ++i)
    {
      ConvertStyle(rules[i].m_rule->GetLine(), m_visualScale, penInfos[i]);

      infos[i] = &penInfos[i];

      if (rules[i].m_transparent)
        penInfos[i].m_color.a = 100;

      resIDs[i] = m_pScreen->invalidHandle();
    }

    // map array of pens
    if (m_pScreen->mapInfo(&infos[0], &resIDs[0], count))
    {
      for (size_t i = 0; i < count; ++i)
        rules[i].SetID(ThreadSlot(), resIDs[i]);
    }
    else
    {
      buffer_vector<m2::PointU, 8> rects;
      for (unsigned i = 0; i < count; ++i)
        rects.push_back(infos[i]->resourceSize());
      LOG(LERROR, ("couldn't successfully pack a sequence of path styles as a whole :" , rects));

      return;
    }
  }

  // draw path with array of rules
  for (size_t i = 0; i < count; ++i)
    m_pScreen->drawPath(&path.m_path[0],
                        path.m_path.size(),
                        -path.GetOffset(),
                        rules[i].GetID(ThreadSlot()),
                        rules[i].m_depth);
}

void Drawer::drawArea(di::AreaInfo const & area, di::DrawRule const & rule)
{
  // DO NOT cache 'id' in pRule, because one rule can use in drawPath and drawArea.
  // Leave CBaseRule::m_id for drawPath. mapColor working fast enough.

  graphics::Brush::Info info;
  ConvertStyle(rule.m_rule->GetArea(), info);

  uint32_t const id = m_pScreen->mapInfo(info);
  ASSERT ( id != -1, () );

  m_pScreen->drawTrianglesList(&area.m_path[0], area.m_path.size(), id, rule.m_depth);
}

void Drawer::drawText(m2::PointD const & pt,
                      graphics::EPosition pos,
                      di::FeatureStyler const & fs,
                      di::DrawRule const & rule,
                      di::FeatureInfo::FeatureID const & id)
{
  graphics::FontDesc primaryFont;
  m2::PointD primaryOffset;
  ConvertStyle(rule.m_rule->GetCaption(0), m_visualScale, primaryFont, primaryOffset);
  primaryFont.SetRank(fs.m_popRank);

  graphics::FontDesc secondaryFont;
  m2::PointD secondaryOffset;
  if (rule.m_rule->GetCaption(1))
  {
    ConvertStyle(rule.m_rule->GetCaption(1), m_visualScale, secondaryFont, secondaryOffset);
    secondaryFont.SetRank(fs.m_popRank);
  }

  graphics::StraightTextElement::Params params;
  params.m_depth = rule.m_depth;
  params.m_fontDesc = primaryFont;
  params.m_auxFontDesc = secondaryFont;
  params.m_offset = primaryOffset;
  params.m_log2vis = true;
  params.m_pivot = pt;
  params.m_position = pos;
  params.m_logText = strings::MakeUniString(fs.m_primaryText);
  params.m_auxLogText = strings::MakeUniString(fs.m_secondaryText);
  params.m_doSplit = true;
  params.m_useAllParts = false;
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawTextEx(params);
}

void Drawer::drawPathText(di::PathInfo const & path,
                          di::FeatureStyler const & fs,
                          di::DrawRule const & rule)
{
  graphics::FontDesc font;
  m2::PointD offset;
  ConvertStyle(rule.m_rule->GetCaption(0), m_visualScale, font, offset);

  if (fs.m_offsets.empty())
    return;

  m_pScreen->drawPathText(font,
                          &path.m_path[0],
                          path.m_path.size(),
                          fs.GetPathName(),
                          path.GetFullLength(),
                          path.GetOffset(),
                          &fs.m_offsets[0],
                          fs.m_offsets.size(),
                          rule.m_depth);
}

void Drawer::drawPathNumber(di::PathInfo const & path,
                            di::FeatureStyler const & fs)
{
  int const textHeight = static_cast<int>(11 * m_visualScale);
  m2::PointD pt;
  double const length = path.GetFullLength();
  if (length >= (fs.m_refText.size() + 2) * textHeight)
  {
    size_t const count = size_t(length / 1000.0) + 2;

    for (size_t j = 1; j < count; ++j)
    {
      if (path.GetSmPoint(double(j) / double(count), pt))
      {
        graphics::FontDesc fontDesc(
          textHeight,
          graphics::Color(150, 75, 0, 255),   // brown
          true,
          graphics::Color(255, 255, 255, 255));

        m_pScreen->drawText(fontDesc,
                            pt,
                            graphics::EPosCenter,
                            fs.m_refText,
                            0,
                            true);
      }
    }
  }
}

graphics::Screen * Drawer::screen() const
{
  return m_pScreen.get();
}

double Drawer::VisualScale() const
{
  return m_visualScale;
}

void Drawer::SetScale(int level)
{
  m_level = level;
}

void Drawer::Draw(di::FeatureInfo const & fi)
{
  di::FeatureInfo::FeatureID const & id = fi.m_id;
  buffer_vector<di::DrawRule, 8> const & rules = fi.m_styler.m_rules;
  buffer_vector<di::DrawRule, 8> pathRules;

  bool const isPath = !fi.m_pathes.empty();
  bool const isArea = !fi.m_areas.empty();

  // separating path rules from other
  for (size_t i = 0; i < rules.size(); ++i)
  {
    drule::BaseRule const * pRule = rules[i].m_rule;

    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCaption = pRule->GetCaption(0) != 0;

    if (!isCaption && isPath && !hasSymbol && (pRule->GetLine() != 0))
      pathRules.push_back(rules[i]);
  }

  if (!pathRules.empty())
  {
    for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
      drawPath(*i, pathRules.data(), pathRules.size());
  }

  for (size_t i = 0; i < rules.size(); ++i)
  {
    drule::BaseRule const * pRule = rules[i].m_rule;
    double const depth = rules[i].m_depth;

    bool const isCaption = pRule->GetCaption(0) != 0;
    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCircle = pRule->GetCircle() != 0;

    if (!isCaption)
    {
      // draw area
      if (isArea)
      {
        bool const isFill = pRule->GetArea() != 0;
        bool const hasSym = hasSymbol && ((pRule->GetType() & drule::way) != 0);

        for (list<di::AreaInfo>::const_iterator i = fi.m_areas.begin(); i != fi.m_areas.end(); ++i)
        {
          if (isFill)
            drawArea(*i, di::DrawRule(pRule, depth, false));
          else if (hasSym)
            drawSymbol(i->GetCenter(), graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
        }
      }

      // draw point symbol
      if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0))
      {
        if (hasSymbol)
          drawSymbol(fi.m_point, graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
        else if (isCircle)
          drawCircle(fi.m_point, graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
      }
    }
    else
    {
      if (!fi.m_styler.m_primaryText.empty() && (pRule->GetCaption(0) != 0))
      {
        bool isN = ((pRule->GetType() & drule::way) != 0);

        graphics::EPosition textPosition = graphics::EPosCenter;
        if (pRule->GetCaption(0)->has_offset_y())
        {
          if (pRule->GetCaption(0)->offset_y() > 0)
            textPosition = graphics::EPosUnder;
          else
            textPosition = graphics::EPosAbove;
        }
        if (pRule->GetCaption(0)->has_offset_x())
        {
          if (pRule->GetCaption(0)->offset_x() > 0)
            textPosition = graphics::EPosRight;
          else
            textPosition = graphics::EPosLeft;
        }

        // draw area text
        if (isArea/* && isN*/)
        {
          for (list<di::AreaInfo>::const_iterator i = fi.m_areas.begin(); i != fi.m_areas.end(); ++i)
            drawText(i->GetCenter(), textPosition, fi.m_styler, di::DrawRule(pRule, depth, false), id);
        }

        // draw way name
        if (isPath && !isArea && isN && !fi.m_styler.FilterTextSize(pRule))
        {
          for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
            drawPathText(*i, fi.m_styler, di::DrawRule(pRule, depth, false));
        }

        // draw point text
        isN = ((pRule->GetType() & drule::node) != 0);
        if (!isPath && !isArea && isN)
          drawText(fi.m_point, textPosition, fi.m_styler, di::DrawRule(pRule, depth, false), id);
      }
    }
  }

  // draw road numbers
  if (isPath && !fi.m_styler.m_refText.empty() && m_level >= 12)
  {
    for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
      drawPathNumber(*i, fi.m_styler);
  }
}

int Drawer::ThreadSlot() const
{
  return m_pScreen->threadSlot();
}
<commit_msg>[map] circles for polygons<commit_after>#include "drawer.hpp"
#include "proto_to_styles.hpp"
#include "feature_styler.hpp"

#include "../std/bind.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/scales.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/resource_manager.hpp"
#include "../graphics/straight_text_element.hpp"

#include "../indexer/drules_include.hpp"
#include "../indexer/feature.hpp"

#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/buffer_vector.hpp"

Drawer::Params::Params()
  : m_visualScale(1)
{
}

Drawer::Drawer(Params const & params)
  : m_visualScale(params.m_visualScale)
{
  m_pScreen.reset(new graphics::Screen(params));

  for (unsigned i = 0; i < m_pScreen->pipelinesCount(); ++i)
    m_pScreen->addClearPageFn(i, bind(&Drawer::ClearResourceCache, ThreadSlot(), i), 0);
}

namespace
{
  struct DoMakeInvalidRule
  {
    size_t m_threadSlot;
    uint32_t m_pipelineIDMask;

    DoMakeInvalidRule(size_t threadSlot, uint8_t pipelineID)
      : m_threadSlot(threadSlot), m_pipelineIDMask(pipelineID << 24)
    {}

    void operator() (int, int, int, drule::BaseRule * p)
    {
      if ((p->GetID(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID(m_threadSlot);
      if ((p->GetID2(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID2(m_threadSlot);
    }
  };
}

void Drawer::ClearResourceCache(size_t threadSlot, uint8_t pipelineID)
{
  drule::rules().ForEachRule(DoMakeInvalidRule(threadSlot, pipelineID));
}

void Drawer::beginFrame()
{
  m_pScreen->beginFrame();
}

void Drawer::endFrame()
{
  m_pScreen->endFrame();
}

void Drawer::clear(graphics::Color const & c, bool clearRT, float depth, bool clearDepth)
{
  m_pScreen->clear(c, clearRT, depth, clearDepth);
}

void Drawer::onSize(int w, int h)
{
  m_pScreen->onSize(w, h);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        string const & symbolName,
                        graphics::EPosition pos,
                        double depth)
{
  m_pScreen->drawSymbol(pt, symbolName, pos, depth);
}

void Drawer::drawCircle(m2::PointD const & pt,
                        graphics::EPosition pos,
                        di::DrawRule const & rule,
                        di::FeatureInfo::FeatureID const & id)
{
  graphics::Circle::Info ci;
  ConvertStyle(rule.m_rule->GetCircle(), m_visualScale, ci);

  graphics::CircleElement::Params params;

  params.m_depth = rule.m_depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_ci = ci;
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawCircle(params);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        graphics::EPosition pos,
                        di::DrawRule const & rule,
                        di::FeatureInfo::FeatureID const & id)
{
  graphics::Icon::Info info;
  ConvertStyle(rule.m_rule->GetSymbol(), info);

  graphics::SymbolElement::Params params;
  params.m_depth = rule.m_depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_info = info;
  params.m_renderer = m_pScreen.get();
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawSymbol(params);
}

void Drawer::drawPath(di::PathInfo const & path, di::DrawRule const * rules, size_t count)
{
  // if any rule needs caching - cache as a whole vector
  bool flag = false;
  for (size_t i = 0; i < count; ++i)
  {
    if (rules[i].GetID(m_pScreen->threadSlot()) == drule::BaseRule::empty_id)
    {
      flag = true;
      break;
    }
  }

  buffer_vector<graphics::Pen::Info, 8> penInfos(count);
  buffer_vector<graphics::Resource::Info const*, 8> infos(count);
  buffer_vector<uint32_t, 8> resIDs(count);

  if (flag)
  {
    // collect graphics::PenInfo into array and pack them as a whole
    for (size_t i = 0; i < count; ++i)
    {
      ConvertStyle(rules[i].m_rule->GetLine(), m_visualScale, penInfos[i]);

      infos[i] = &penInfos[i];

      if (rules[i].m_transparent)
        penInfos[i].m_color.a = 100;

      resIDs[i] = m_pScreen->invalidHandle();
    }

    // map array of pens
    if (m_pScreen->mapInfo(&infos[0], &resIDs[0], count))
    {
      for (size_t i = 0; i < count; ++i)
        rules[i].SetID(ThreadSlot(), resIDs[i]);
    }
    else
    {
      buffer_vector<m2::PointU, 8> rects;
      for (unsigned i = 0; i < count; ++i)
        rects.push_back(infos[i]->resourceSize());
      LOG(LERROR, ("couldn't successfully pack a sequence of path styles as a whole :" , rects));

      return;
    }
  }

  // draw path with array of rules
  for (size_t i = 0; i < count; ++i)
    m_pScreen->drawPath(&path.m_path[0],
                        path.m_path.size(),
                        -path.GetOffset(),
                        rules[i].GetID(ThreadSlot()),
                        rules[i].m_depth);
}

void Drawer::drawArea(di::AreaInfo const & area, di::DrawRule const & rule)
{
  // DO NOT cache 'id' in pRule, because one rule can use in drawPath and drawArea.
  // Leave CBaseRule::m_id for drawPath. mapColor working fast enough.

  graphics::Brush::Info info;
  ConvertStyle(rule.m_rule->GetArea(), info);

  uint32_t const id = m_pScreen->mapInfo(info);
  ASSERT ( id != -1, () );

  m_pScreen->drawTrianglesList(&area.m_path[0], area.m_path.size(), id, rule.m_depth);
}

void Drawer::drawText(m2::PointD const & pt,
                      graphics::EPosition pos,
                      di::FeatureStyler const & fs,
                      di::DrawRule const & rule,
                      di::FeatureInfo::FeatureID const & id)
{
  graphics::FontDesc primaryFont;
  m2::PointD primaryOffset;
  ConvertStyle(rule.m_rule->GetCaption(0), m_visualScale, primaryFont, primaryOffset);
  primaryFont.SetRank(fs.m_popRank);

  graphics::FontDesc secondaryFont;
  m2::PointD secondaryOffset;
  if (rule.m_rule->GetCaption(1))
  {
    ConvertStyle(rule.m_rule->GetCaption(1), m_visualScale, secondaryFont, secondaryOffset);
    secondaryFont.SetRank(fs.m_popRank);
  }

  graphics::StraightTextElement::Params params;
  params.m_depth = rule.m_depth;
  params.m_fontDesc = primaryFont;
  params.m_auxFontDesc = secondaryFont;
  params.m_offset = primaryOffset;
  params.m_log2vis = true;
  params.m_pivot = pt;
  params.m_position = pos;
  params.m_logText = strings::MakeUniString(fs.m_primaryText);
  params.m_auxLogText = strings::MakeUniString(fs.m_secondaryText);
  params.m_doSplit = true;
  params.m_useAllParts = false;
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawTextEx(params);
}

void Drawer::drawPathText(di::PathInfo const & path,
                          di::FeatureStyler const & fs,
                          di::DrawRule const & rule)
{
  graphics::FontDesc font;
  m2::PointD offset;
  ConvertStyle(rule.m_rule->GetCaption(0), m_visualScale, font, offset);

  if (fs.m_offsets.empty())
    return;

  m_pScreen->drawPathText(font,
                          &path.m_path[0],
                          path.m_path.size(),
                          fs.GetPathName(),
                          path.GetFullLength(),
                          path.GetOffset(),
                          &fs.m_offsets[0],
                          fs.m_offsets.size(),
                          rule.m_depth);
}

void Drawer::drawPathNumber(di::PathInfo const & path,
                            di::FeatureStyler const & fs)
{
  int const textHeight = static_cast<int>(11 * m_visualScale);
  m2::PointD pt;
  double const length = path.GetFullLength();
  if (length >= (fs.m_refText.size() + 2) * textHeight)
  {
    size_t const count = size_t(length / 1000.0) + 2;

    for (size_t j = 1; j < count; ++j)
    {
      if (path.GetSmPoint(double(j) / double(count), pt))
      {
        graphics::FontDesc fontDesc(
          textHeight,
          graphics::Color(150, 75, 0, 255),   // brown
          true,
          graphics::Color(255, 255, 255, 255));

        m_pScreen->drawText(fontDesc,
                            pt,
                            graphics::EPosCenter,
                            fs.m_refText,
                            0,
                            true);
      }
    }
  }
}

graphics::Screen * Drawer::screen() const
{
  return m_pScreen.get();
}

double Drawer::VisualScale() const
{
  return m_visualScale;
}

void Drawer::SetScale(int level)
{
  m_level = level;
}

void Drawer::Draw(di::FeatureInfo const & fi)
{
  di::FeatureInfo::FeatureID const & id = fi.m_id;
  buffer_vector<di::DrawRule, 8> const & rules = fi.m_styler.m_rules;
  buffer_vector<di::DrawRule, 8> pathRules;

  bool const isPath = !fi.m_pathes.empty();
  bool const isArea = !fi.m_areas.empty();

  // separating path rules from other
  for (size_t i = 0; i < rules.size(); ++i)
  {
    drule::BaseRule const * pRule = rules[i].m_rule;

    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCaption = pRule->GetCaption(0) != 0;

    if (!isCaption && isPath && !hasSymbol && (pRule->GetLine() != 0))
      pathRules.push_back(rules[i]);
  }

  if (!pathRules.empty())
  {
    for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
      drawPath(*i, pathRules.data(), pathRules.size());
  }

  for (size_t i = 0; i < rules.size(); ++i)
  {
    drule::BaseRule const * pRule = rules[i].m_rule;
    double const depth = rules[i].m_depth;

    bool const isCaption = pRule->GetCaption(0) != 0;
    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCircle = pRule->GetCircle() != 0;

    if (!isCaption)
    {
      // draw area
      if (isArea)
      {
        bool const isFill = pRule->GetArea() != 0;
        bool const isWay = (pRule->GetType() & drule::way) != 0;

        for (list<di::AreaInfo>::const_iterator i = fi.m_areas.begin(); i != fi.m_areas.end(); ++i)
        {
          if (isFill)
            drawArea(*i, di::DrawRule(pRule, depth, false));
          else if (hasSymbol && !isWay)
            drawSymbol(i->GetCenter(), graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
          else if (isCircle && !isWay)
            drawCircle(i->GetCenter(), graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
        }
      }

      // draw point symbol
      if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0))
      {
        if (hasSymbol)
          drawSymbol(fi.m_point, graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
        else if (isCircle)
          drawCircle(fi.m_point, graphics::EPosCenter, di::DrawRule(pRule, depth, false), id);
      }
    }
    else
    {
      if (!fi.m_styler.m_primaryText.empty() && (pRule->GetCaption(0) != 0))
      {
        bool isN = ((pRule->GetType() & drule::way) != 0);

        graphics::EPosition textPosition = graphics::EPosCenter;
        if (pRule->GetCaption(0)->has_offset_y())
        {
          if (pRule->GetCaption(0)->offset_y() > 0)
            textPosition = graphics::EPosUnder;
          else
            textPosition = graphics::EPosAbove;
        }
        if (pRule->GetCaption(0)->has_offset_x())
        {
          if (pRule->GetCaption(0)->offset_x() > 0)
            textPosition = graphics::EPosRight;
          else
            textPosition = graphics::EPosLeft;
        }

        // draw area text
        if (isArea/* && isN*/)
        {
          for (list<di::AreaInfo>::const_iterator i = fi.m_areas.begin(); i != fi.m_areas.end(); ++i)
            drawText(i->GetCenter(), textPosition, fi.m_styler, di::DrawRule(pRule, depth, false), id);
        }

        // draw way name
        if (isPath && !isArea && isN && !fi.m_styler.FilterTextSize(pRule))
        {
          for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
            drawPathText(*i, fi.m_styler, di::DrawRule(pRule, depth, false));
        }

        // draw point text
        isN = ((pRule->GetType() & drule::node) != 0);
        if (!isPath && !isArea && isN)
          drawText(fi.m_point, textPosition, fi.m_styler, di::DrawRule(pRule, depth, false), id);
      }
    }
  }

  // draw road numbers
  if (isPath && !fi.m_styler.m_refText.empty() && m_level >= 12)
  {
    for (list<di::PathInfo>::const_iterator i = fi.m_pathes.begin(); i != fi.m_pathes.end(); ++i)
      drawPathNumber(*i, fi.m_styler);
  }
}

int Drawer::ThreadSlot() const
{
  return m_pScreen->threadSlot();
}
<|endoftext|>


<commit_before>/* Calf DSP Library
 * Preset management.
 *
 * Copyright (C) 2001-2007 Krzysztof Foltman
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

#include <expat.h>
#include <calf/preset.h>
#include <calf/giface.h>
#include <calf/utils.h>

using namespace std;
using namespace calf_plugins;
using namespace calf_utils;

extern calf_plugins::preset_list &calf_plugins::get_builtin_presets()
{
    static calf_plugins::preset_list plist;
    return plist;
}

extern calf_plugins::preset_list &calf_plugins::get_user_presets()
{
    static calf_plugins::preset_list plist;
    return plist;
}

std::string plugin_preset::to_xml()
{
    std::stringstream ss;
    ss << "<preset bank=\"" << bank << "\" program=\"" << program << "\" plugin=\"" << xml_escape(plugin) << "\" name=\"" << xml_escape(name) << "\">\n";
    for (unsigned int i = 0; i < values.size(); i++) {
        if (i < param_names.size())
            ss << "  <param name=\"" << xml_escape(param_names[i]) << "\" value=\"" << values[i] << "\" />\n";
        else
            ss << "  <param value=\"" << values[i] << "\" />\n";
    }
    for (map<string, string>::iterator i = variables.begin(); i != variables.end(); i++)
    {
        ss << "  <var name=\"" << xml_escape(i->first) << "\">" << xml_escape(i->second) << "</var>\n";
    }
    ss << "</preset>\n";
    return ss.str();
}

void plugin_preset::activate(plugin_ctl_iface *plugin)
{
    // First, clear everything to default values (in case some parameters or variables are missing)
    plugin->clear_preset();

    map<string, int> names;
    int count = plugin->get_param_count();
    // this is deliberately done in two separate loops - if you wonder why, just think for a while :)
    for (int i = 0; i < count; i++)
        names[plugin->get_param_props(i)->name] = i;
    for (int i = 0; i < count; i++)
        names[plugin->get_param_props(i)->short_name] = i;
    // no support for unnamed parameters... tough luck :)
    for (unsigned int i = 0; i < min(param_names.size(), values.size()); i++)
    {
        map<string, int>::iterator pos = names.find(param_names[i]);
        if (pos == names.end()) {
            // XXXKF should have a mechanism for notifying a GUI
            printf("Warning: unknown parameter %s for plugin %s\n", param_names[i].c_str(), this->plugin.c_str());
            continue;
        }
        plugin->set_param_value(pos->second, values[i]);
    }
    for (map<string, string>::iterator i = variables.begin(); i != variables.end(); i++)
    {
        printf("configure %s: %s\n", i->first.c_str(), i->second.c_str());
        plugin->configure(i->first.c_str(), i->second.c_str());
    }
}

void plugin_preset::get_from(plugin_ctl_iface *plugin)
{
    int count = plugin->get_param_count();
    for (int i = 0; i < count; i++) {
        param_names.push_back(plugin->get_param_props(i)->short_name);
        values.push_back(plugin->get_param_value(i));
    }
    struct store_obj: public send_configure_iface
    {
        map<string, string> *data;
        void send_configure(const char *key, const char *value)
        {
            (*data)[key] = value;
        }
    } tmp;
    variables.clear();
    tmp.data = &variables;
    plugin->send_configures(&tmp);
}

string calf_plugins::preset_list::get_preset_filename(bool builtin)
{
    if (builtin)
    {
        return PKGLIBDIR "/presets.xml";
    }
    else
    {
        const char *home = getenv("HOME");
        return string(home)+"/.calfpresets";
    }
}

void preset_list::xml_start_element_handler(void *user_data, const char *name, const char *attrs[])
{
    preset_list &self = *(preset_list *)user_data;
    parser_state &state = self.state;
    plugin_preset &parser_preset = self.parser_preset;
    switch(state)
    {
    case START:
        if (!strcmp(name, "presets")) {
            state = LIST;
            return;
        }
        break;
    case LIST:
        if (!strcmp(name, "preset")) {

            parser_preset.bank = parser_preset.program = 0;
            parser_preset.name = "";
            parser_preset.plugin = "";
            parser_preset.param_names.clear();
            parser_preset.values.clear();
            parser_preset.variables.clear();
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) self.parser_preset.name = attrs[1];
                else
                if (!strcmp(attrs[0], "plugin")) self.parser_preset.plugin = attrs[1];
            }
            // autonumbering of programs for DSSI
            if (!self.last_preset_ids.count(self.parser_preset.plugin))
                self.last_preset_ids[self.parser_preset.plugin] = 0;
            self.parser_preset.program = ++self.last_preset_ids[self.parser_preset.plugin];
            self.parser_preset.bank = (self.parser_preset.program >> 7);
            self.parser_preset.program &= 127;
            state = PRESET;
            return;
        }
        break;
    case PRESET:
        if (!strcmp(name, "param")) {
            std::string name;
            float value = 0.f;
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) name = attrs[1];
                else
                if (!strcmp(attrs[0], "value")) {
                    istringstream str(attrs[1]);
                    str >> value;
                }
            }
            self.parser_preset.param_names.push_back(name);
            self.parser_preset.values.push_back(value);
            state = VALUE;
            return;
        }
        if (!strcmp(name, "var")) {
            self.current_key = "";
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) self.current_key = attrs[1];
            }
            if (self.current_key.empty())
                throw preset_exception("No name specified for preset variable", "", 0);
            self.parser_preset.variables[self.current_key].clear();
            state = VAR;
            return;
        }
        break;
    case VALUE:
        // no nested elements allowed inside <param>
        break;
    case VAR:
        // no nested elements allowed inside <var>
        break;
    }
    // g_warning("Invalid XML element: %s", name);
    throw preset_exception("Invalid XML element: %s", name, 0);
}

void preset_list::xml_end_element_handler(void *user_data, const char *name)
{
    preset_list &self = *(preset_list *)user_data;
    preset_vector &presets = self.presets;
    parser_state &state = self.state;
    switch(state)
    {
    case START:
        break;
    case LIST:
        if (!strcmp(name, "presets")) {
            state = START;
            return;
        }
        break;
    case PRESET:
        if (!strcmp(name, "preset")) {
            presets.push_back(self.parser_preset);
            state = LIST;
            return;
        }
        break;
    case VALUE:
        if (!strcmp(name, "param")) {
            state = PRESET;
            return;
        }
        break;
    case VAR:
        if (!strcmp(name, "var")) {
            state = PRESET;
            return;
        }
        break;
    }
    throw preset_exception("Invalid XML element close: %s", name, 0);
}

void preset_list::xml_character_data_handler(void *user_data, const XML_Char *data, int len)
{
    preset_list &self = *(preset_list *)user_data;
    parser_state &state = self.state;
    if (state == VAR)
    {
        self.parser_preset.variables[self.current_key] += string(data, len);
        return;
    }
}

bool preset_list::load_defaults(bool builtin)
{
    try {
        struct stat st;
        string name = preset_list::get_preset_filename(builtin);
        if (!stat(name.c_str(), &st)) {
            load(name.c_str());
            if (!presets.empty())
                return true;
        }
    }
    catch(preset_exception &ex)
    {
        return false;
    }
    return false;
}

void preset_list::parse(const std::string &data)
{
    state = START;
    XML_Parser parser = XML_ParserCreate("UTF-8");
    XML_SetUserData(parser, this);
    XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler);
    XML_SetCharacterDataHandler(parser, xml_character_data_handler);
    XML_Status status = XML_Parse(parser, data.c_str(), data.length(), 1);
    if (status == XML_STATUS_ERROR) {
        string err = string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ";
        XML_ParserFree(parser);
        throw preset_exception(err, "string", errno);
    }
    XML_ParserFree(parser);
}

void preset_list::load(const char *filename)
{
    state = START;
    XML_Parser parser = XML_ParserCreate("UTF-8");
    XML_SetUserData(parser, this);
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
        throw preset_exception("Could not load the presets from ", filename, errno);
    XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler);
    XML_SetCharacterDataHandler(parser, xml_character_data_handler);
    char buf[4096];
    do
    {
        int len = read(fd, buf, 4096);
        // XXXKF not an optimal error/EOF handling :)
        if (len <= 0)
            break;
        XML_Status status = XML_Parse(parser, buf, len, 0);
        if (status == XML_STATUS_ERROR)
            throw preset_exception(string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ", filename, errno);
    } while(1);
    XML_Status status = XML_Parse(parser, buf, 0, 1);
    close(fd);
    if (status == XML_STATUS_ERROR)
    {
        string err = string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ";
        XML_ParserFree(parser);
        throw preset_exception(err, filename, errno);
    }
    XML_ParserFree(parser);
}

void preset_list::save(const char *filename)
{
    string xml = "<presets>\n";
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        xml += presets[i].to_xml();
    }
    xml += "</presets>";
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0640);
    if (fd < 0 || ((unsigned)write(fd, xml.c_str(), xml.length()) != xml.length()))
        throw preset_exception("Could not save the presets in ", filename, errno);
    close(fd);
}

void preset_list::get_for_plugin(preset_vector &vec, const char *plugin)
{
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        if (presets[i].plugin == plugin)
            vec.push_back(presets[i]);
    }
}

void preset_list::add(const plugin_preset &sp)
{
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        if (presets[i].plugin == sp.plugin && presets[i].name == sp.name)
        {
            presets[i] = sp;
            return;
        }
    }
    presets.push_back(sp);
}
<commit_msg>+ Preset system: do not produce float values for string ports in presets<commit_after>/* Calf DSP Library
 * Preset management.
 *
 * Copyright (C) 2001-2007 Krzysztof Foltman
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

#include <expat.h>
#include <calf/preset.h>
#include <calf/giface.h>
#include <calf/utils.h>

using namespace std;
using namespace calf_plugins;
using namespace calf_utils;

extern calf_plugins::preset_list &calf_plugins::get_builtin_presets()
{
    static calf_plugins::preset_list plist;
    return plist;
}

extern calf_plugins::preset_list &calf_plugins::get_user_presets()
{
    static calf_plugins::preset_list plist;
    return plist;
}

std::string plugin_preset::to_xml()
{
    std::stringstream ss;
    ss << "<preset bank=\"" << bank << "\" program=\"" << program << "\" plugin=\"" << xml_escape(plugin) << "\" name=\"" << xml_escape(name) << "\">\n";
    for (unsigned int i = 0; i < values.size(); i++) {
        if (i < param_names.size())
            ss << "  <param name=\"" << xml_escape(param_names[i]) << "\" value=\"" << values[i] << "\" />\n";
        else
            ss << "  <param value=\"" << values[i] << "\" />\n";
    }
    for (map<string, string>::iterator i = variables.begin(); i != variables.end(); i++)
    {
        ss << "  <var name=\"" << xml_escape(i->first) << "\">" << xml_escape(i->second) << "</var>\n";
    }
    ss << "</preset>\n";
    return ss.str();
}

void plugin_preset::activate(plugin_ctl_iface *plugin)
{
    // First, clear everything to default values (in case some parameters or variables are missing)
    plugin->clear_preset();

    map<string, int> names;
    int count = plugin->get_param_count();
    // this is deliberately done in two separate loops - if you wonder why, just think for a while :)
    for (int i = 0; i < count; i++)
        names[plugin->get_param_props(i)->name] = i;
    for (int i = 0; i < count; i++)
        names[plugin->get_param_props(i)->short_name] = i;
    // no support for unnamed parameters... tough luck :)
    for (unsigned int i = 0; i < min(param_names.size(), values.size()); i++)
    {
        map<string, int>::iterator pos = names.find(param_names[i]);
        if (pos == names.end()) {
            // XXXKF should have a mechanism for notifying a GUI
            printf("Warning: unknown parameter %s for plugin %s\n", param_names[i].c_str(), this->plugin.c_str());
            continue;
        }
        plugin->set_param_value(pos->second, values[i]);
    }
    for (map<string, string>::iterator i = variables.begin(); i != variables.end(); i++)
    {
        printf("configure %s: %s\n", i->first.c_str(), i->second.c_str());
        plugin->configure(i->first.c_str(), i->second.c_str());
    }
}

void plugin_preset::get_from(plugin_ctl_iface *plugin)
{
    int count = plugin->get_param_count();
    for (int i = 0; i < count; i++) {
        if ((plugin->get_param_props(i)->flags & PF_TYPEMASK) >= PF_STRING)
            continue;
        param_names.push_back(plugin->get_param_props(i)->short_name);
        values.push_back(plugin->get_param_value(i));
    }
    struct store_obj: public send_configure_iface
    {
        map<string, string> *data;
        void send_configure(const char *key, const char *value)
        {
            (*data)[key] = value;
        }
    } tmp;
    variables.clear();
    tmp.data = &variables;
    plugin->send_configures(&tmp);
}

string calf_plugins::preset_list::get_preset_filename(bool builtin)
{
    if (builtin)
    {
        return PKGLIBDIR "/presets.xml";
    }
    else
    {
        const char *home = getenv("HOME");
        return string(home)+"/.calfpresets";
    }
}

void preset_list::xml_start_element_handler(void *user_data, const char *name, const char *attrs[])
{
    preset_list &self = *(preset_list *)user_data;
    parser_state &state = self.state;
    plugin_preset &parser_preset = self.parser_preset;
    switch(state)
    {
    case START:
        if (!strcmp(name, "presets")) {
            state = LIST;
            return;
        }
        break;
    case LIST:
        if (!strcmp(name, "preset")) {

            parser_preset.bank = parser_preset.program = 0;
            parser_preset.name = "";
            parser_preset.plugin = "";
            parser_preset.param_names.clear();
            parser_preset.values.clear();
            parser_preset.variables.clear();
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) self.parser_preset.name = attrs[1];
                else
                if (!strcmp(attrs[0], "plugin")) self.parser_preset.plugin = attrs[1];
            }
            // autonumbering of programs for DSSI
            if (!self.last_preset_ids.count(self.parser_preset.plugin))
                self.last_preset_ids[self.parser_preset.plugin] = 0;
            self.parser_preset.program = ++self.last_preset_ids[self.parser_preset.plugin];
            self.parser_preset.bank = (self.parser_preset.program >> 7);
            self.parser_preset.program &= 127;
            state = PRESET;
            return;
        }
        break;
    case PRESET:
        if (!strcmp(name, "param")) {
            std::string name;
            float value = 0.f;
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) name = attrs[1];
                else
                if (!strcmp(attrs[0], "value")) {
                    istringstream str(attrs[1]);
                    str >> value;
                }
            }
            self.parser_preset.param_names.push_back(name);
            self.parser_preset.values.push_back(value);
            state = VALUE;
            return;
        }
        if (!strcmp(name, "var")) {
            self.current_key = "";
            for(; *attrs; attrs += 2) {
                if (!strcmp(attrs[0], "name")) self.current_key = attrs[1];
            }
            if (self.current_key.empty())
                throw preset_exception("No name specified for preset variable", "", 0);
            self.parser_preset.variables[self.current_key].clear();
            state = VAR;
            return;
        }
        break;
    case VALUE:
        // no nested elements allowed inside <param>
        break;
    case VAR:
        // no nested elements allowed inside <var>
        break;
    }
    // g_warning("Invalid XML element: %s", name);
    throw preset_exception("Invalid XML element: %s", name, 0);
}

void preset_list::xml_end_element_handler(void *user_data, const char *name)
{
    preset_list &self = *(preset_list *)user_data;
    preset_vector &presets = self.presets;
    parser_state &state = self.state;
    switch(state)
    {
    case START:
        break;
    case LIST:
        if (!strcmp(name, "presets")) {
            state = START;
            return;
        }
        break;
    case PRESET:
        if (!strcmp(name, "preset")) {
            presets.push_back(self.parser_preset);
            state = LIST;
            return;
        }
        break;
    case VALUE:
        if (!strcmp(name, "param")) {
            state = PRESET;
            return;
        }
        break;
    case VAR:
        if (!strcmp(name, "var")) {
            state = PRESET;
            return;
        }
        break;
    }
    throw preset_exception("Invalid XML element close: %s", name, 0);
}

void preset_list::xml_character_data_handler(void *user_data, const XML_Char *data, int len)
{
    preset_list &self = *(preset_list *)user_data;
    parser_state &state = self.state;
    if (state == VAR)
    {
        self.parser_preset.variables[self.current_key] += string(data, len);
        return;
    }
}

bool preset_list::load_defaults(bool builtin)
{
    try {
        struct stat st;
        string name = preset_list::get_preset_filename(builtin);
        if (!stat(name.c_str(), &st)) {
            load(name.c_str());
            if (!presets.empty())
                return true;
        }
    }
    catch(preset_exception &ex)
    {
        return false;
    }
    return false;
}

void preset_list::parse(const std::string &data)
{
    state = START;
    XML_Parser parser = XML_ParserCreate("UTF-8");
    XML_SetUserData(parser, this);
    XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler);
    XML_SetCharacterDataHandler(parser, xml_character_data_handler);
    XML_Status status = XML_Parse(parser, data.c_str(), data.length(), 1);
    if (status == XML_STATUS_ERROR) {
        string err = string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ";
        XML_ParserFree(parser);
        throw preset_exception(err, "string", errno);
    }
    XML_ParserFree(parser);
}

void preset_list::load(const char *filename)
{
    state = START;
    XML_Parser parser = XML_ParserCreate("UTF-8");
    XML_SetUserData(parser, this);
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
        throw preset_exception("Could not load the presets from ", filename, errno);
    XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler);
    XML_SetCharacterDataHandler(parser, xml_character_data_handler);
    char buf[4096];
    do
    {
        int len = read(fd, buf, 4096);
        // XXXKF not an optimal error/EOF handling :)
        if (len <= 0)
            break;
        XML_Status status = XML_Parse(parser, buf, len, 0);
        if (status == XML_STATUS_ERROR)
            throw preset_exception(string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ", filename, errno);
    } while(1);
    XML_Status status = XML_Parse(parser, buf, 0, 1);
    close(fd);
    if (status == XML_STATUS_ERROR)
    {
        string err = string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser))+ " in ";
        XML_ParserFree(parser);
        throw preset_exception(err, filename, errno);
    }
    XML_ParserFree(parser);
}

void preset_list::save(const char *filename)
{
    string xml = "<presets>\n";
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        xml += presets[i].to_xml();
    }
    xml += "</presets>";
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0640);
    if (fd < 0 || ((unsigned)write(fd, xml.c_str(), xml.length()) != xml.length()))
        throw preset_exception("Could not save the presets in ", filename, errno);
    close(fd);
}

void preset_list::get_for_plugin(preset_vector &vec, const char *plugin)
{
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        if (presets[i].plugin == plugin)
            vec.push_back(presets[i]);
    }
}

void preset_list::add(const plugin_preset &sp)
{
    for (unsigned int i = 0; i < presets.size(); i++)
    {
        if (presets[i].plugin == sp.plugin && presets[i].name == sp.name)
        {
            presets[i] = sp;
            return;
        }
    }
    presets.push_back(sp);
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2013       Adrian Draghici <draghici.adrian.b@gmail.com>
//

#include "KmlPlaylistTagWriter.h"

#include "GeoDataPlaylist.h"
#include "GeoDataTypes.h"
#include "GeoWriter.h"
#include "KmlElementDictionary.h"

namespace Marble
{

static GeoTagWriterRegistrar s_writerTour(
        GeoTagWriter::QualifiedName( GeoDataTypes::GeoDataPlaylistType,
                                     kml::kmlTag_nameSpace22 ),
        new KmlPlaylistTagWriter );

bool KmlPlaylistTagWriter::write( const GeoNode *node, GeoWriter& writer ) const
{
    const GeoDataPlaylist *playlist = static_cast<const GeoDataPlaylist*>( node );

    writer.writeStartElement( "gx:Playlist" );

    for ( int i = 0; i < playlist->size(); i++ ) {
        writeTourPrimitive( playlist->primitive( i ), writer );
    }

    writer.writeEndElement();

    return true;
}

void KmlPlaylistTagWriter::writeTourPrimitive( const GeoNode *primitive, GeoWriter& writer ) const
{

    if ( primitive->nodeType() == GeoDataTypes::GeoDataTourControlType ) {
        writeTourControl( static_cast<const GeoDataTourControl*>( primitive ), writer );
    }
    else if ( primitive->nodeType() == GeoDataTypes::GeoDataFlyToType ) {
        writeElement( static_cast<const GeoDataFlyTo*>( primitive ), writer );
    }
}

void KmlPlaylistTagWriter::writeTourControl( const GeoDataTourControl* tourControl, GeoWriter& writer ) const
{
    writer.writeStartElement( kml::kmlTag_TourControl );
    if ( !tourControl->id().isEmpty() ) {
        writer.writeAttribute( "id", tourControl->id() );
    }

    writer.writeElement( kml::kmlTag_playMode, playModeToString( tourControl->playMode() ) );

    writer.writeEndElement();
}

QString KmlPlaylistTagWriter::playModeToString( GeoDataTourControl::PlayMode playMode ) const
{
    switch (playMode)
    {
    case GeoDataTourControl::Play:   return "play";
    case GeoDataTourControl::Pause:  return "pause";
    default:                         return "";
    }
}

}
<commit_msg>Fix name (copy/paste error). Don't cast.<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2013       Adrian Draghici <draghici.adrian.b@gmail.com>
//

#include "KmlPlaylistTagWriter.h"

#include "GeoDataPlaylist.h"
#include "GeoDataTypes.h"
#include "GeoWriter.h"
#include "KmlElementDictionary.h"

namespace Marble
{

static GeoTagWriterRegistrar s_writerPlaylist(
        GeoTagWriter::QualifiedName( GeoDataTypes::GeoDataPlaylistType,
                                     kml::kmlTag_nameSpace22 ),
        new KmlPlaylistTagWriter );

bool KmlPlaylistTagWriter::write( const GeoNode *node, GeoWriter& writer ) const
{
    const GeoDataPlaylist *playlist = static_cast<const GeoDataPlaylist*>( node );

    writer.writeStartElement( "gx:Playlist" );

    for ( int i = 0; i < playlist->size(); i++ ) {
        writeTourPrimitive( playlist->primitive( i ), writer );
    }

    writer.writeEndElement();

    return true;
}

void KmlPlaylistTagWriter::writeTourPrimitive( const GeoNode *primitive, GeoWriter& writer ) const
{

    if ( primitive->nodeType() == GeoDataTypes::GeoDataTourControlType ) {
        writeTourControl( static_cast<const GeoDataTourControl*>( primitive ), writer );
    }
    else if ( primitive->nodeType() == GeoDataTypes::GeoDataFlyToType ) {
        writeElement( primitive, writer );
    }
}

void KmlPlaylistTagWriter::writeTourControl( const GeoDataTourControl* tourControl, GeoWriter& writer ) const
{
    writer.writeStartElement( kml::kmlTag_TourControl );
    if ( !tourControl->id().isEmpty() ) {
        writer.writeAttribute( "id", tourControl->id() );
    }

    writer.writeElement( kml::kmlTag_playMode, playModeToString( tourControl->playMode() ) );

    writer.writeEndElement();
}

QString KmlPlaylistTagWriter::playModeToString( GeoDataTourControl::PlayMode playMode ) const
{
    switch (playMode)
    {
    case GeoDataTourControl::Play:   return "play";
    case GeoDataTourControl::Pause:  return "pause";
    default:                         return "";
    }
}

}
<|endoftext|>