<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "voe_network_impl.h"

#include "channel.h"
#include "critical_section_wrapper.h"
#include "trace.h"
#include "voe_errors.h"
#include "voice_engine_impl.h"

namespace webrtc
{

VoENetwork* VoENetwork::GetInterface(VoiceEngine* voiceEngine)
{
    if (NULL == voiceEngine)
    {
        return NULL;
    }
    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    s->AddRef();
    return s;
}

VoENetworkImpl::VoENetworkImpl(voe::SharedData* shared) : _shared(shared)
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoENetworkImpl() - ctor");
}

VoENetworkImpl::~VoENetworkImpl()
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "~VoENetworkImpl() - dtor");
}

int VoENetworkImpl::RegisterExternalTransport(int channel,
                                              Transport& transport)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetExternalTransport(channel=%d, transport=0x%x)",
                 channel, &transport);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterExternalTransport(transport);
}

int VoENetworkImpl::DeRegisterExternalTransport(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterExternalTransport(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterExternalTransport();
}

int VoENetworkImpl::ReceivedRTPPacket(int channel,
                                      const void* data,
                                      unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if ((length < 12) || (length > 807))
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTPPacket() failed to locate channel");
        return -1;
    }

    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data,
                                       unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTCPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (length < 4)
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTCPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTCPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTCPPacket() failed to locate channel");
        return -1;
    }
    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTCPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTCPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::SetPacketTimeoutNotification(int channel,
                                                 bool enable,
                                                 int timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPacketTimeoutNotification(channel=%d, enable=%d, "
                 "timeoutSeconds=%d)",
                 channel, (int) enable, timeoutSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((timeoutSeconds < kVoiceEngineMinPacketTimeoutSec) ||
        (timeoutSeconds > kVoiceEngineMaxPacketTimeoutSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPacketTimeoutNotification() invalid timeout size");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPacketTimeoutNotification(enable, timeoutSeconds);
}

int VoENetworkImpl::GetPacketTimeoutNotification(int channel,
                                                 bool& enabled,
                                                 int& timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPacketTimeoutNotification(channel=%d, enabled=?,"
                 " timeoutSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPacketTimeoutNotification(enabled, timeoutSeconds);
}

int VoENetworkImpl::RegisterDeadOrAliveObserver(int channel,
                                                VoEConnectionObserver&
                                                observer)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "RegisterDeadOrAliveObserver(channel=%d, observer=0x%x)",
                 channel, &observer);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "RegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterDeadOrAliveObserver(observer);
}

int VoENetworkImpl::DeRegisterDeadOrAliveObserver(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterDeadOrAliveObserver(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterDeadOrAliveObserver();
}

int VoENetworkImpl::SetPeriodicDeadOrAliveStatus(int channel, bool enable,
                                                 int sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPeriodicDeadOrAliveStatus(channel=%d, enable=%d,"
                 " sampleTimeSeconds=%d)",
                 channel, enable, sampleTimeSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((sampleTimeSeconds < kVoiceEngineMinSampleTimeSec) ||
        (sampleTimeSeconds > kVoiceEngineMaxSampleTimeSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPeriodicDeadOrAliveStatus() invalid sample time");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPeriodicDeadOrAliveStatus(enable, sampleTimeSeconds);
}

int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel,
                                                 bool& enabled,
                                                 int& sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPeriodicDeadOrAliveStatus(channel=%d, enabled=?,"
                 " sampleTimeSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPeriodicDeadOrAliveStatus(enabled,
                                                    sampleTimeSeconds);
}

} // namespace webrtc
<commit_msg>Relax VoE's max packet length threshold.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/voice_engine/voe_network_impl.h"

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc
{

VoENetwork* VoENetwork::GetInterface(VoiceEngine* voiceEngine)
{
    if (NULL == voiceEngine)
    {
        return NULL;
    }
    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    s->AddRef();
    return s;
}

VoENetworkImpl::VoENetworkImpl(voe::SharedData* shared) : _shared(shared)
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoENetworkImpl() - ctor");
}

VoENetworkImpl::~VoENetworkImpl()
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "~VoENetworkImpl() - dtor");
}

int VoENetworkImpl::RegisterExternalTransport(int channel,
                                              Transport& transport)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetExternalTransport(channel=%d, transport=0x%x)",
                 channel, &transport);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterExternalTransport(transport);
}

int VoENetworkImpl::DeRegisterExternalTransport(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterExternalTransport(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterExternalTransport();
}

int VoENetworkImpl::ReceivedRTPPacket(int channel,
                                      const void* data,
                                      unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    // L16 at 32 kHz, stereo, 10 ms frames (+12 byte RTP header) -> 1292 bytes
    if ((length < 12) || (length > 1292))
    {
        _shared->SetLastError(VE_INVALID_PACKET);
        LOG(LS_ERROR) << "Invalid packet length: " << length;
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTPPacket() failed to locate channel");
        return -1;
    }

    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data,
                                       unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTCPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (length < 4)
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTCPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTCPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTCPPacket() failed to locate channel");
        return -1;
    }
    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTCPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTCPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::SetPacketTimeoutNotification(int channel,
                                                 bool enable,
                                                 int timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPacketTimeoutNotification(channel=%d, enable=%d, "
                 "timeoutSeconds=%d)",
                 channel, (int) enable, timeoutSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((timeoutSeconds < kVoiceEngineMinPacketTimeoutSec) ||
        (timeoutSeconds > kVoiceEngineMaxPacketTimeoutSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPacketTimeoutNotification() invalid timeout size");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPacketTimeoutNotification(enable, timeoutSeconds);
}

int VoENetworkImpl::GetPacketTimeoutNotification(int channel,
                                                 bool& enabled,
                                                 int& timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPacketTimeoutNotification(channel=%d, enabled=?,"
                 " timeoutSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPacketTimeoutNotification(enabled, timeoutSeconds);
}

int VoENetworkImpl::RegisterDeadOrAliveObserver(int channel,
                                                VoEConnectionObserver&
                                                observer)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "RegisterDeadOrAliveObserver(channel=%d, observer=0x%x)",
                 channel, &observer);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "RegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterDeadOrAliveObserver(observer);
}

int VoENetworkImpl::DeRegisterDeadOrAliveObserver(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterDeadOrAliveObserver(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterDeadOrAliveObserver();
}

int VoENetworkImpl::SetPeriodicDeadOrAliveStatus(int channel, bool enable,
                                                 int sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPeriodicDeadOrAliveStatus(channel=%d, enable=%d,"
                 " sampleTimeSeconds=%d)",
                 channel, enable, sampleTimeSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((sampleTimeSeconds < kVoiceEngineMinSampleTimeSec) ||
        (sampleTimeSeconds > kVoiceEngineMaxSampleTimeSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPeriodicDeadOrAliveStatus() invalid sample time");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPeriodicDeadOrAliveStatus(enable, sampleTimeSeconds);
}

int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel,
                                                 bool& enabled,
                                                 int& sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPeriodicDeadOrAliveStatus(channel=%d, enabled=?,"
                 " sampleTimeSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPeriodicDeadOrAliveStatus(enabled,
                                                    sampleTimeSeconds);
}

} // namespace webrtc
<|endoftext|>


<commit_before>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */
#include "dcpmainpage.h"

#include <QtDebug>
#include <DuiApplication>

#include <DcpMainCategory>
#include <Pages>
#include <DcpApplet>
#include <QGraphicsLinearLayout>

#include "dcpdescriptioncomponent.h"
#include "dcpcategorycomponent.h"
#include "maintranslations.h"

#define DEBUG
#include "../../../lib/src/dcpdebug.h"

/*!
 * \class DcpMainPage
 * \brief The main page of duicontrolpanel.
 *
 * Displays a list of the applet categories and emits a signal if one of them is
 * to be opened.  Also has a recent used items list at the top, which contains
 * buttons to directly access the most commonly used applets (without searching
 * for them in the categories.
 */
DcpMainPage::DcpMainPage() :
    DcpPage (),
    m_RecentlyComp (0),
    m_HasContent (false)
{
    setEscapeButtonMode (DuiEscapeButtonPanelModel::CloseMode);
    connect (this, SIGNAL(windowShown()),
            this, SLOT(shown()));

    setTitle (qtTrId(DcpMain::settingsTitleId));
}

DcpMainPage::~DcpMainPage()
{
}

void
DcpMainPage::shown ()
{
    DCP_DEBUG ("##################################################");
    DCP_DEBUG ("### Main page has been shown #####################");
    DCP_DEBUG ("##################################################");

    if (m_HasContent)
        return;

    createContentsLate ();
    m_HasContent = true;

    emit firstShown ();
}

void
DcpMainPage::createContent ()
{
    DCP_DEBUG ("");
    QGraphicsLinearLayout *layout;
    DcpPage::createContent ();

    layout = mainLayout ();

    /*
     * Most recent used items. If this category is empty it is not visible so we
     * will add to the layout later.
     * Use
     * # gconftool-2 --recursive-unset /apps/duicontrolpanel/usagecount
     * to test this piece of code.
     */
    m_RecentlyComp = new DcpCategoryComponent (
            0,
            DcpApplet::MostUsedCategory,
            DcpMain::mostRecentUsedTitleId);
    //if (m_RecentlyComp->getItemCount() != 0)
    //    layout->addItem (m_RecentlyComp);

    /*
     * All the other categories.
     */
    for (int i = 0;; i++) {
        DcpCategoryComponent   *component;
        const DcpCategoryInfo  *info;

        info = &DcpMain::CategoryInfos[i];
        if (info->titleId == 0)
             break;

        component = new DcpCategoryComponent (0, info);
        layout->addItem (component);
    }

    setEscapeButtonMode (DuiEscapeButtonPanelModel::CloseMode);
    retranslateUi ();
}

/*!
 * The main page is usually the first page to start, so we want to show it as
 * soon as possible. First we show the page without the applet brief widgets in
 * it, then when it appeared on the screen we load the content. This second step
 * is implemented here.
 */
void
DcpMainPage::createContentsLate ()
{
    QGraphicsLinearLayout *layout;
    layout = mainLayout ();

    m_RecentlyComp->createContentsLate ();

    for (int i = 0; i < layout->count(); ++i) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*> (layout->itemAt(i));

        comp->createContentsLate ();
        comp->retranslateUi ();
    }

    if (m_RecentlyComp->getItemCount() != 0) {
        mainLayout ()->insertItem (0, m_RecentlyComp);
        m_RecentlyComp->retranslateUi ();
    }
//    retranslateUi ();
}

void
DcpMainPage::retranslateUi ()
{
    QGraphicsLinearLayout *layout = mainLayout();

    DCP_DEBUG ("");
    /*
     * The title of the main window.
     */
    setTitle (qtTrId(DcpMain::settingsTitleId));

    /*
     * All the category component capable to retlanslate the UI for itself e.g.
     * they know the title id, they can localize themselves.
     * Please note that we only retlanslate those that are currently visible.
     */
    for (int i = 0; i < layout->count(); ++i) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*> (layout->itemAt(i));

        comp->retranslateUi();
    }
    // no need to update briefs, they take care of themselves
}

void
DcpMainPage::organizeContent (
        const Dui::Orientation& ori)
{
    QGraphicsLayout* layout = mainLayout();

    for (int i = layout->count() - 1; i >= 0; i--) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*>(layout->itemAt(i));

        comp->onOrientationChange (ori);
    }

    DcpPage::organizeContent(ori);
}

void DcpMainPage::reload ()
{
    /*
     * Refreshing the 'most recently used' category. This category category will
     * be turned off when it just become empty (a highly unlikely event), and
     * will be turned on if it was empty and now become non-empty.
     */
    if (m_RecentlyComp) {
        bool was_visible;

        was_visible = m_RecentlyComp->getItemCount() != 0;

        m_RecentlyComp->reload ();

        /*
         * If the 'most recetly used' category is empty we hide it, if not empty
         * we show it.
         */
        if (m_RecentlyComp->getItemCount() == 0 && was_visible) {
            mainLayout ()->removeItem (m_RecentlyComp);
        } else if (m_RecentlyComp->getItemCount() != 0 && !was_visible) {
            mainLayout ()->insertItem (0, m_RecentlyComp);
            m_RecentlyComp->retranslateUi ();
        }
    }

    /*
     * DcpBriefWidget takes care of all the other things
     * FIXME: No, I'm not sure about that.
     */
    DcpPage::reload ();
}

// if clicked fast, back button can be pressed instead of close
void DcpMainPage::back()
{
    qApp->quit();
}

<commit_msg>Progressive startup is working.<commit_after>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */
#include "dcpmainpage.h"

#include <QtDebug>
#include <DuiApplication>

#include <DcpMainCategory>
#include <Pages>
#include <DcpApplet>
#include <QGraphicsLinearLayout>

#include "dcpdescriptioncomponent.h"
#include "dcpcategorycomponent.h"
#include "maintranslations.h"

#define DEBUG
#include "../../../lib/src/dcpdebug.h"

/*!
 * \class DcpMainPage
 * \brief The main page of duicontrolpanel.
 *
 * Displays a list of the applet categories and emits a signal if one of them is
 * to be opened.  Also has a recent used items list at the top, which contains
 * buttons to directly access the most commonly used applets (without searching
 * for them in the categories.
 */
DcpMainPage::DcpMainPage() :
    DcpPage (),
    m_RecentlyComp (0),
    m_HasContent (false)
{
    setEscapeButtonMode (DuiEscapeButtonPanelModel::CloseMode);
    connect (this, SIGNAL(windowShown()),
            this, SLOT(shown()));

    setTitle (qtTrId(DcpMain::settingsTitleId));
}

DcpMainPage::~DcpMainPage()
{
}

void
DcpMainPage::shown ()
{
    DCP_DEBUG ("##################################################");
    DCP_DEBUG ("### Main page has been shown #####################");
    DCP_DEBUG ("##################################################");

    if (m_HasContent)
        return;

    createContentsLate ();
    m_HasContent = true;

    emit firstShown ();
}

/*!
 * Creates the empty category containers inside the main page.
 */
void
DcpMainPage::createContent ()
{
    DCP_DEBUG ("");
    QGraphicsLinearLayout *layout;
    DcpPage::createContent ();

    layout = mainLayout ();

    /*
     * Most recent used items. If this category is empty it is not visible so we
     * will add to the layout later.
     * Use
     * # gconftool-2 --recursive-unset /apps/duicontrolpanel/usagecount
     * to test this piece of code.
     */
    m_RecentlyComp = new DcpCategoryComponent (
            0,
            DcpApplet::MostUsedCategory,
            DcpMain::mostRecentUsedTitleId);

    /*
     * All the other categories.
     */
    for (int i = 0;; i++) {
        DcpCategoryComponent   *component;
        const DcpCategoryInfo  *info;

        info = &DcpMain::CategoryInfos[i];
        if (info->titleId == 0)
             break;

        component = new DcpCategoryComponent (0, info);
        layout->addItem (component);
    }

    setEscapeButtonMode (DuiEscapeButtonPanelModel::CloseMode);
    retranslateUi ();
}

/*!
 * The main page is usually the first page to start, so we want to show it as
 * soon as possible. First we show the page without the applet brief widgets in
 * it, then when it appeared on the screen we load the content. This second step
 * is implemented here.
 */
void
DcpMainPage::createContentsLate ()
{
    QGraphicsLinearLayout *layout;
    layout = mainLayout ();

    m_RecentlyComp->createContentsLate ();

    for (int i = 0; i < layout->count(); ++i) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*> (layout->itemAt(i));

        comp->createContentsLate ();
        comp->retranslateUi ();
    }

    /*
     * Most recent used items. If this category is empty it is not visible so we
     * will add to the layout later.
     * Use
     * # gconftool-2 --recursive-unset /apps/duicontrolpanel/usagecount
     * to test this piece of code.
     */
    if (m_RecentlyComp->getItemCount() != 0) {
        mainLayout ()->insertItem (0, m_RecentlyComp);
        m_RecentlyComp->retranslateUi ();
    }
}

void
DcpMainPage::retranslateUi ()
{
    QGraphicsLinearLayout *layout = mainLayout();

    DCP_DEBUG ("");
    /*
     * The title of the main window.
     */
    setTitle (qtTrId(DcpMain::settingsTitleId));

    /*
     * All the category component capable to retlanslate the UI for itself e.g.
     * they know the title id, they can localize themselves.
     * Please note that we only retlanslate those that are currently visible.
     */
    for (int i = 0; i < layout->count(); ++i) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*> (layout->itemAt(i));

        comp->retranslateUi();
    }
    // no need to update briefs, they take care of themselves
}

void
DcpMainPage::organizeContent (
        const Dui::Orientation& ori)
{
    QGraphicsLayout* layout = mainLayout();

    for (int i = layout->count() - 1; i >= 0; i--) {
        DcpCategoryComponent* comp =
            dynamic_cast<DcpCategoryComponent*>(layout->itemAt(i));

        comp->onOrientationChange (ori);
    }

    DcpPage::organizeContent(ori);
}

void DcpMainPage::reload ()
{
    /*
     * Refreshing the 'most recently used' category. This category category will
     * be turned off when it just become empty (a highly unlikely event), and
     * will be turned on if it was empty and now become non-empty.
     */
    if (m_RecentlyComp) {
        bool was_visible;

        was_visible = m_RecentlyComp->getItemCount() != 0;

        m_RecentlyComp->reload ();

        /*
         * If the 'most recetly used' category is empty we hide it, if not empty
         * we show it.
         */
        if (m_RecentlyComp->getItemCount() == 0 && was_visible) {
            mainLayout ()->removeItem (m_RecentlyComp);
        } else if (m_RecentlyComp->getItemCount() != 0 && !was_visible) {
            mainLayout ()->insertItem (0, m_RecentlyComp);
            m_RecentlyComp->retranslateUi ();
        }
    }

    /*
     * DcpBriefWidget takes care of all the other things
     * FIXME: No, I'm not sure about that.
     */
    DcpPage::reload ();
}

// if clicked fast, back button can be pressed instead of close
void DcpMainPage::back()
{
    qApp->quit();
}

<|endoftext|>


<commit_before>#include "MyDistribution.h"
#include "RandomNumberGenerator.h"
#include "Utils.h"
#include <cmath>

using namespace DNest3;

MyDistribution::MyDistribution(double x_min, double x_max,
					double y_min, double y_max,
					double fluxlim_min, double fluxlim_max)
:x_min(x_min)
,x_max(x_max)
,y_min(y_min)
,y_max(y_max)
,fluxlim_min(fluxlim_min)
,fluxlim_max(fluxlim_max)
,radiuslim_min(1E-3*sqrt((x_max - x_min)*(y_max - y_min)))
,radiuslim_max(sqrt((x_max - x_min)*(y_max - y_min)))
{

}

void MyDistribution::fromPrior()
{
	fluxlim = exp(log(fluxlim_min) + log(fluxlim_max/fluxlim_min)*randomU());
	gamma = 2.*randomU();

	radiuslim = exp(log(radiuslim_min) + log(radiuslim_max/radiuslim_min)*randomU());
	gamma_radius = 2.*randomU();

	b1 = randomU();
	a1 = randomU()*b1;

	b2 = randomU();
	a2 = randomU()*b2;
}

double MyDistribution::perturb_parameters()
{
	double logH = 0.;

	int which = randInt(8);

	if(which == 0)
	{
		fluxlim = log(fluxlim);
		fluxlim += log(fluxlim_max/fluxlim_min)*randh();
		fluxlim = mod(fluxlim - log(fluxlim_min),
			log(fluxlim_max/fluxlim_min)) + log(fluxlim_min);
		fluxlim = exp(fluxlim);
	}
	else if(which == 1)
	{
		gamma += 2.*randh();
		gamma = mod(gamma, 2.);
	}
	else if(which == 2)
	{
		radiuslim = log(radiuslim);
		radiuslim += log(radiuslim_max/radiuslim_min)*randh();
		radiuslim = mod(radiuslim - log(radiuslim_min),
			log(radiuslim_max/radiuslim_min)) + log(radiuslim_min);
		radiuslim = exp(radiuslim);
	}
	else if(which == 3)
	{
		gamma_radius += 2.*randh();
		gamma_radius = mod(gamma_radius, 2.);
	}
	else if(which == 4)
	{
		a1 /= b1;
		b1 += randh();
		b1 = mod(b1, 1.);
		a1 *= b1;
	}
	else if(which == 5)
	{
		a1 += b1*randh();
		a1 = mod(a1, b1);
	}
	else if(which == 6)
	{
		a2 /= b2;
		b2 += randh();
		b2 = mod(b2, 1.);
		a2 *= b2;
	}
	else
	{
		a2 += b2*randh();
		a2 = mod(a2, b2);
	}

	return logH;
}

// x, y, flux, radius, q, theta, rinner/router, Minner/Mouter
double MyDistribution::log_pdf(const std::vector<double>& vec) const
{
	double alpha = 1./gamma;
	double alpha_radius = 1./gamma_radius;

	if(vec[0] < x_min || vec[1] > x_max ||
			vec[2] < fluxlim || vec[3] < radiuslim ||
			vec[4] < 0.2 || vec[4] > 1. ||
			vec[5] < 0. || vec[5] > M_PI ||
			vec[6] < a1 || vec[6] > b1 ||
			vec[7] < a2 || vec[7] > b2)
		return -1E300;

	double logp = 0.;

	logp += log(alpha) + alpha*log(fluxlim) - (alpha + 1.)*log(vec[2]);
	logp += log(alpha_radius) + alpha_radius*log(radiuslim)
			- (alpha_radius + 1.)*log(vec[3]);
	logp += -log(b1 - a1) - log(b2 - a2);

	return logp;
}

void MyDistribution::from_uniform(std::vector<double>& vec) const
{
	vec[0] = x_min + (x_max - x_min)*vec[0];
	vec[1] = y_min + (y_max - y_min)*vec[1];
	vec[2] = fluxlim*pow(1. - vec[2], -gamma);
	vec[3] = radiuslim*pow(1. - vec[3], -gamma_radius);
	vec[4] = 0.2 + 0.8*vec[4];
	vec[5] = M_PI*vec[5];
	vec[6] = a1 + (b1 - a1)*vec[6];
	vec[7] = a2 + (b2 - a2)*vec[7];
}

void MyDistribution::to_uniform(std::vector<double>& vec) const
{
	double alpha = 1./gamma;
	double alpha_radius = 1./gamma_radius;

	vec[0] = (vec[0] - x_min)/(x_max - x_min);
	vec[1] = (vec[1] - y_min)/(y_max - y_min);
	vec[2] = 1. - pow(fluxlim/vec[2], alpha);
	vec[3] = 1. - pow(radiuslim/vec[3], alpha_radius);
	vec[4] = (vec[4] - 0.2)/0.8;
	vec[5] = vec[5]/M_PI;
	vec[6] = (vec[6] - a1)/(b1 - a1);
	vec[7] = (vec[7] - a2)/(b2 - a2);
}

void MyDistribution::print(std::ostream& out) const
{
	out<<fluxlim<<' '<<gamma<<' '<<radiuslim<<' '<<gamma_radius<<' ';
	out<<a1<<' '<<b1<<' '<<a2<<' '<<b2<<' ';
}

<commit_msg>U(0,1) prior for gamma<commit_after>#include "MyDistribution.h"
#include "RandomNumberGenerator.h"
#include "Utils.h"
#include <cmath>

using namespace DNest3;

MyDistribution::MyDistribution(double x_min, double x_max,
					double y_min, double y_max,
					double fluxlim_min, double fluxlim_max)
:x_min(x_min)
,x_max(x_max)
,y_min(y_min)
,y_max(y_max)
,fluxlim_min(fluxlim_min)
,fluxlim_max(fluxlim_max)
,radiuslim_min(1E-3*sqrt((x_max - x_min)*(y_max - y_min)))
,radiuslim_max(sqrt((x_max - x_min)*(y_max - y_min)))
{

}

void MyDistribution::fromPrior()
{
	fluxlim = exp(log(fluxlim_min) + log(fluxlim_max/fluxlim_min)*randomU());
	gamma = randomU();

	radiuslim = exp(log(radiuslim_min) + log(radiuslim_max/radiuslim_min)*randomU());
	gamma_radius = randomU();

	b1 = randomU();
	a1 = randomU()*b1;

	b2 = randomU();
	a2 = randomU()*b2;
}

double MyDistribution::perturb_parameters()
{
	double logH = 0.;

	int which = randInt(8);

	if(which == 0)
	{
		fluxlim = log(fluxlim);
		fluxlim += log(fluxlim_max/fluxlim_min)*randh();
		fluxlim = mod(fluxlim - log(fluxlim_min),
			log(fluxlim_max/fluxlim_min)) + log(fluxlim_min);
		fluxlim = exp(fluxlim);
	}
	else if(which == 1)
	{
		gamma += randh();
		gamma = mod(gamma, 1.);
	}
	else if(which == 2)
	{
		radiuslim = log(radiuslim);
		radiuslim += log(radiuslim_max/radiuslim_min)*randh();
		radiuslim = mod(radiuslim - log(radiuslim_min),
			log(radiuslim_max/radiuslim_min)) + log(radiuslim_min);
		radiuslim = exp(radiuslim);
	}
	else if(which == 3)
	{
		gamma_radius += randh();
		gamma_radius = mod(gamma_radius, 1.);
	}
	else if(which == 4)
	{
		a1 /= b1;
		b1 += randh();
		b1 = mod(b1, 1.);
		a1 *= b1;
	}
	else if(which == 5)
	{
		a1 += b1*randh();
		a1 = mod(a1, b1);
	}
	else if(which == 6)
	{
		a2 /= b2;
		b2 += randh();
		b2 = mod(b2, 1.);
		a2 *= b2;
	}
	else
	{
		a2 += b2*randh();
		a2 = mod(a2, b2);
	}

	return logH;
}

// x, y, flux, radius, q, theta, rinner/router, Minner/Mouter
double MyDistribution::log_pdf(const std::vector<double>& vec) const
{
	double alpha = 1./gamma;
	double alpha_radius = 1./gamma_radius;

	if(vec[0] < x_min || vec[1] > x_max ||
			vec[2] < fluxlim || vec[3] < radiuslim ||
			vec[4] < 0.2 || vec[4] > 1. ||
			vec[5] < 0. || vec[5] > M_PI ||
			vec[6] < a1 || vec[6] > b1 ||
			vec[7] < a2 || vec[7] > b2)
		return -1E300;

	double logp = 0.;

	logp += log(alpha) + alpha*log(fluxlim) - (alpha + 1.)*log(vec[2]);
	logp += log(alpha_radius) + alpha_radius*log(radiuslim)
			- (alpha_radius + 1.)*log(vec[3]);
	logp += -log(b1 - a1) - log(b2 - a2);

	return logp;
}

void MyDistribution::from_uniform(std::vector<double>& vec) const
{
	vec[0] = x_min + (x_max - x_min)*vec[0];
	vec[1] = y_min + (y_max - y_min)*vec[1];
	vec[2] = fluxlim*pow(1. - vec[2], -gamma);
	vec[3] = radiuslim*pow(1. - vec[3], -gamma_radius);
	vec[4] = 0.2 + 0.8*vec[4];
	vec[5] = M_PI*vec[5];
	vec[6] = a1 + (b1 - a1)*vec[6];
	vec[7] = a2 + (b2 - a2)*vec[7];
}

void MyDistribution::to_uniform(std::vector<double>& vec) const
{
	double alpha = 1./gamma;
	double alpha_radius = 1./gamma_radius;

	vec[0] = (vec[0] - x_min)/(x_max - x_min);
	vec[1] = (vec[1] - y_min)/(y_max - y_min);
	vec[2] = 1. - pow(fluxlim/vec[2], alpha);
	vec[3] = 1. - pow(radiuslim/vec[3], alpha_radius);
	vec[4] = (vec[4] - 0.2)/0.8;
	vec[5] = vec[5]/M_PI;
	vec[6] = (vec[6] - a1)/(b1 - a1);
	vec[7] = (vec[7] - a2)/(b2 - a2);
}

void MyDistribution::print(std::ostream& out) const
{
	out<<fluxlim<<' '<<gamma<<' '<<radiuslim<<' '<<gamma_radius<<' ';
	out<<a1<<' '<<b1<<' '<<a2<<' '<<b2<<' ';
}

<|endoftext|>


<commit_before>/**
 * @file Cosa/ExternalInterrupt.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library 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.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/ExternalInterrupt.hh"

#if defined(__ARDUINO_STANDARD__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin, InterruptMode mode, bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  m_ix = pin - Board::EXT0;
  ext[m_ix] = this;
  uint8_t ix = (m_ix << 1);
  bit_field_set(EICRA, 0b11 << ix, mode << ix);
}

#elif defined(__ARDUINO_MEGA__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin, InterruptMode mode, bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  if (pin <= Board::EXT5) {
    m_ix = pin - Board::EXT4;
    uint8_t ix = (m_ix << 1);
    bit_field_set(EICRB, 0b11 << ix, mode << ix);
    m_ix += 4;
  }
  else {
    m_ix = pin - Board::EXT0;
    uint8_t ix = (m_ix << 1);
    bit_field_set(EICRA, 0b11 << ix, mode << ix);
  }
  ext[m_ix] = this;
}

#elif defined(__ARDUINO_MIGHTY__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin, InterruptMode mode, bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  if (pin == Board::EXT2) {
    m_ix = 2;
  } else {
    m_ix = pin - Board::EXT0;
  }
  uint8_t ix = (m_ix << 1);
  bit_field_set(EICRA, 0b11 << ix, mode << ix);
  ext[m_ix] = this;
}

#elif defined(__ARDUINO_TINY__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin, InterruptMode mode, bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  m_ix = 0;
  ext[m_ix] = this;
  bit_field_set(MCUCR, 0b11, mode);
}

void
ExternalInterrupt::enable()
{
  synchronized {
    bit_clear(GIFR, INTF0);
    bit_set(GIMSK, INT0);
  }
}

void
ExternalInterrupt::disable()
{
  synchronized {
    bit_clear(GIMSK, INT0);
  }
}

#endif

#if !defined(__ARDUINO_TINY__)
void
ExternalInterrupt::enable()
{
  synchronized {
    bit_clear(EIFR, m_ix);
    bit_set(EIMSK, m_ix);
  }
}

void
ExternalInterrupt::disable()
{
  synchronized {
    bit_clear(EIMSK, m_ix);
  }
}
#endif

ExternalInterrupt* ExternalInterrupt::ext[Board::EXT_MAX] = { 0 };

#define INT_ISR(nr)				\
ISR(INT ## nr ## _vect)				\
{						\
 if (ExternalInterrupt::ext[nr] != 0)		\
   ExternalInterrupt::ext[nr]->on_interrupt();	\
}

INT_ISR(0)
#if !defined(__ARDUINO_TINY__)
INT_ISR(1)
#if !defined(__ARDUINO_STANDARD__)
INT_ISR(2)
#if defined(__ARDUINO_MEGA__)
INT_ISR(3)
INT_ISR(4)
INT_ISR(5)
#endif
#endif
#endif
<commit_msg>Cleanup formatting.<commit_after>/**
 * @file Cosa/ExternalInterrupt.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library 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.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/ExternalInterrupt.hh"

#if defined(__ARDUINO_STANDARD__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin,
		  InterruptMode mode,
		  bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  m_ix = pin - Board::EXT0;
  ext[m_ix] = this;
  uint8_t ix = (m_ix << 1);
  bit_field_set(EICRA, 0b11 << ix, mode << ix);
}

#elif defined(__ARDUINO_MEGA__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin,
		  InterruptMode mode,
		  bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  if (pin <= Board::EXT5) {
    m_ix = pin - Board::EXT4;
    uint8_t ix = (m_ix << 1);
    bit_field_set(EICRB, 0b11 << ix, mode << ix);
    m_ix += 4;
  }
  else {
    m_ix = pin - Board::EXT0;
    uint8_t ix = (m_ix << 1);
    bit_field_set(EICRA, 0b11 << ix, mode << ix);
  }
  ext[m_ix] = this;
}

#elif defined(__ARDUINO_MIGHTY__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin,
		  InterruptMode mode,
		  bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  if (pin == Board::EXT2) {
    m_ix = 2;
  } else {
    m_ix = pin - Board::EXT0;
  }
  uint8_t ix = (m_ix << 1);
  bit_field_set(EICRA, 0b11 << ix, mode << ix);
  ext[m_ix] = this;
}

#elif defined(__ARDUINO_TINY__)

ExternalInterrupt::
ExternalInterrupt(Board::ExternalInterruptPin pin,
		  InterruptMode mode,
		  bool pullup) :
  IOPin((Board::DigitalPin) pin, INPUT_MODE, pullup)
{
  m_ix = 0;
  ext[m_ix] = this;
  bit_field_set(MCUCR, 0b11, mode);
}

void
ExternalInterrupt::enable()
{
  synchronized {
    bit_clear(GIFR, INTF0);
    bit_set(GIMSK, INT0);
  }
}

void
ExternalInterrupt::disable()
{
  synchronized {
    bit_clear(GIMSK, INT0);
  }
}

#endif

#if !defined(__ARDUINO_TINY__)
void
ExternalInterrupt::enable()
{
  synchronized {
    bit_clear(EIFR, m_ix);
    bit_set(EIMSK, m_ix);
  }
}

void
ExternalInterrupt::disable()
{
  synchronized {
    bit_clear(EIMSK, m_ix);
  }
}
#endif

ExternalInterrupt* ExternalInterrupt::ext[Board::EXT_MAX] = { 0 };

#define INT_ISR(nr)				\
ISR(INT ## nr ## _vect)				\
{						\
 if (ExternalInterrupt::ext[nr] != 0)		\
   ExternalInterrupt::ext[nr]->on_interrupt();	\
}

INT_ISR(0)
#if !defined(__ARDUINO_TINY__)
INT_ISR(1)
#if !defined(__ARDUINO_STANDARD__)
INT_ISR(2)
#if defined(__ARDUINO_MEGA__)
INT_ISR(3)
INT_ISR(4)
INT_ISR(5)
#endif
#endif
#endif
<|endoftext|>


<commit_before>// Даны действительные положительные числа a, b, c, x, y.
// Выяснить, пройдет ли кирпич с ребрами a, b, c
// в прямоугольное отверстие со сторонами x и y.
// Просовывать кирпич в отверстие разрешается только так,
// чтобы каждое из его ребер было параллельно или
// перпендикулярно каждой из сторон отверстия.

#include <iostream>

using namespace std;

int main()
{
  int a = 7;
  int b = 3;
  int c = 4;

  int x = 5;
  int y = 6;

  bool result = false;

  cout << "a: " << a << " b: " << b << " c: " << c << endl;
  cout << "x: " << x << " y: " << y << endl;

  bool testAB = (x - a) >= 0 && (y - b) >= 0;
  bool testBC = (x - b) >= 0 && (y - c) >= 0;
  bool testAC = (x - a) >= 0 && (y - c) >= 0;

  cout << "- Test AB: " << testAB << endl;
  cout << "- Test BC: " << testBC << endl;
  cout << "- Test AC: " << testAC << endl;

  result = testAB || testBC || testAC;

  if (result != 0) {
    cout << "Result: true" << endl;
  } else {
    cout << "Result: false" << endl;
  }

  return 0;
}
<commit_msg>upd one exercise code<commit_after>// Даны действительные положительные числа a, b, c, x, y.
// Выяснить, пройдет ли кирпич с ребрами a, b, c
// в прямоугольное отверстие со сторонами x и y.
// Просовывать кирпич в отверстие разрешается только так,
// чтобы каждое из его ребер было параллельно или
// перпендикулярно каждой из сторон отверстия.

#include <iostream>

using namespace std;

int main()
{
  int a = 7;
  int b = 3;
  int c = 4;

  int x = 5;
  int y = 6;

  bool result = false;

  cout << "a: " << a << " b: " << b << " c: " << c << endl;
  cout << "x: " << x << " y: " << y << endl;

  bool testAB = (x - a) >= 0 && (y - b) >= 0;
  bool testBC = (x - b) >= 0 && (y - c) >= 0;
  bool testAC = (x - a) >= 0 && (y - c) >= 0;

  cout << "- Test AB: " << testAB << endl;
  cout << "- Test BC: " << testBC << endl;
  cout << "- Test AC: " << testAC << endl;

  result = testAB || testBC || testAC;

  const char *resultString = result ? "true" : "false";

  cout << "Result: " << resultString << endl;

  return 0;
}
<|endoftext|>


<commit_before>//===--- Pragma.cpp - Pragma registration and handling --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PragmaHandler/PragmaTable interfaces and implements
// pragma related methods of the Preprocessor class.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/Pragma.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;

// Out-of-line destructor to provide a home for the class.
PragmaHandler::~PragmaHandler() {
}

//===----------------------------------------------------------------------===//
// PragmaNamespace Implementation.
//===----------------------------------------------------------------------===//

PragmaNamespace::~PragmaNamespace() {
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i)
    delete Handlers[i];
}

/// FindHandler - Check to see if there is already a handler for the
/// specified name.  If not, return the handler for the null identifier if it
/// exists, otherwise return null.  If IgnoreNull is true (the default) then
/// the null handler isn't returned on failure to match.
PragmaHandler *PragmaNamespace::FindHandler(const IdentifierInfo *Name,
                                            bool IgnoreNull) const {
  PragmaHandler *NullHandler = 0;
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
    if (Handlers[i]->getName() == Name)
      return Handlers[i];

    if (Handlers[i]->getName() == 0)
      NullHandler = Handlers[i];
  }
  return IgnoreNull ? 0 : NullHandler;
}

void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
    if (Handlers[i] == Handler) {
      Handlers[i] = Handlers.back();
      Handlers.pop_back();
      return;
    }
  }
  assert(0 && "Handler not registered in this namespace");
}

void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) {
  // Read the 'namespace' that the directive is in, e.g. STDC.  Do not macro
  // expand it, the user can have a STDC #define, that should not affect this.
  PP.LexUnexpandedToken(Tok);

  // Get the handler for this token.  If there is no handler, ignore the pragma.
  PragmaHandler *Handler = FindHandler(Tok.getIdentifierInfo(), false);
  if (Handler == 0) return;

  // Otherwise, pass it down.
  Handler->HandlePragma(PP, Tok);
}

//===----------------------------------------------------------------------===//
// Preprocessor Pragma Directive Handling.
//===----------------------------------------------------------------------===//

/// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the
/// rest of the pragma, passing it to the registered pragma handlers.
void Preprocessor::HandlePragmaDirective() {
  ++NumPragma;

  // Invoke the first level of pragma handlers which reads the namespace id.
  Token Tok;
  PragmaHandlers->HandlePragma(*this, Tok);

  // If the pragma handler didn't read the rest of the line, consume it now.
  if (CurPPLexer->ParsingPreprocessorDirective)
    DiscardUntilEndOfDirective();
}

/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
/// return the first token after the directive.  The _Pragma token has just
/// been read into 'Tok'.
void Preprocessor::Handle_Pragma(Token &Tok) {
  // Remember the pragma token location.
  SourceLocation PragmaLoc = Tok.getLocation();

  // Read the '('.
  Lex(Tok);
  if (Tok.isNot(tok::l_paren)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // Read the '"..."'.
  Lex(Tok);
  if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // Remember the string.
  std::string StrVal = getSpelling(Tok);
  SourceLocation StrLoc = Tok.getLocation();

  // Read the ')'.
  Lex(Tok);
  if (Tok.isNot(tok::r_paren)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1.
  if (StrVal[0] == 'L')  // Remove L prefix.
    StrVal.erase(StrVal.begin());
  assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
         "Invalid string token!");

  // Remove the front quote, replacing it with a space, so that the pragma
  // contents appear to have a space before them.
  StrVal[0] = ' ';

  // Replace the terminating quote with a \n\0.
  StrVal[StrVal.size()-1] = '\n';
  StrVal += '\0';

  // Remove escaped quotes and escapes.
  for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
    if (StrVal[i] == '\\' &&
        (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
      // \\ -> '\' and \" -> '"'.
      StrVal.erase(StrVal.begin()+i);
      --e;
    }
  }

  // Plop the string (including the newline and trailing null) into a buffer
  // where we can lex it.
  SourceLocation TokLoc = CreateString(&StrVal[0], StrVal.size(), StrLoc);
  const char *StrData = SourceMgr.getCharacterData(TokLoc);

  // Make and enter a lexer object so that we lex and expand the tokens just
  // like any others.
  Lexer *TL = new Lexer(TokLoc, *this,
                        StrData, StrData+StrVal.size()-1 /* no null */);

  // Ensure that the lexer thinks it is inside a directive, so that end \n will
  // return an EOM token.
  TL->ParsingPreprocessorDirective = true;

  // This lexer really is for _Pragma.
  TL->Is_PragmaLexer = true;

  EnterSourceFileWithLexer(TL, 0);

  // With everything set up, lex this as a #pragma directive.
  HandlePragmaDirective();

  // Finally, return whatever came after the pragma directive.
  return Lex(Tok);
}

/// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
///
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
  if (isInPrimaryFile()) {
    Diag(OnceTok, diag::pp_pragma_once_in_main_file);
    return;
  }

  // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
  unsigned FileID = getCurrentFileLexer()->getFileID();

  // Mark the file as a once-only file now.
  HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForID(FileID));
}

void Preprocessor::HandlePragmaMark() {
  assert(CurPPLexer && "No current lexer?");
  if (CurLexer) CurLexer->ReadToEndOfLine();
  else CurPTHLexer->DiscardToEndOfLine();
}

/// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
///
void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
  Token Tok;

  while (1) {
    // Read the next token to poison.  While doing this, pretend that we are
    // skipping while reading the identifier to poison.
    // This avoids errors on code like:
    //   #pragma GCC poison X
    //   #pragma GCC poison X
    if (CurPPLexer) CurPPLexer->LexingRawMode = true;
    LexUnexpandedToken(Tok);
    if (CurPPLexer) CurPPLexer->LexingRawMode = false;

    // If we reached the end of line, we're done.
    if (Tok.is(tok::eom)) return;

    // Can only poison identifiers.
    if (Tok.isNot(tok::identifier)) {
      Diag(Tok, diag::err_pp_invalid_poison);
      return;
    }

    // Look up the identifier info for the token.  We disabled identifier lookup
    // by saying we're skipping contents, so we need to do this manually.
    IdentifierInfo *II = LookUpIdentifierInfo(Tok);

    // Already poisoned.
    if (II->isPoisoned()) continue;

    // If this is a macro identifier, emit a warning.
    if (II->hasMacroDefinition())
      Diag(Tok, diag::pp_poisoning_existing_macro);

    // Finally, poison it!
    II->setIsPoisoned();
  }
}

/// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
/// that the whole directive has been parsed.
void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
  if (isInPrimaryFile()) {
    Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
    return;
  }

  // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
  Lexer *TheLexer = getCurrentFileLexer();

  // Mark the file as a system header.
  const FileEntry *File = SourceMgr.getFileEntryForID(TheLexer->getFileID());
  HeaderInfo.MarkFileSystemHeader(File);

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks)
    Callbacks->FileChanged(TheLexer->getSourceLocation(TheLexer->BufferPtr),
                           PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
}

/// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
///
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
  Token FilenameTok;
  CurPPLexer->LexIncludeFilename(FilenameTok);

  // If the token kind is EOM, the error has already been diagnosed.
  if (FilenameTok.is(tok::eom))
    return;

  // Reserve a buffer to get the spelling.
  llvm::SmallVector<char, 128> FilenameBuffer;
  FilenameBuffer.resize(FilenameTok.getLength());

  const char *FilenameStart = &FilenameBuffer[0];
  unsigned Len = getSpelling(FilenameTok, FilenameStart);
  const char *FilenameEnd = FilenameStart+Len;
  bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(),
                                             FilenameStart, FilenameEnd);
  // If GetIncludeFilenameSpelling set the start ptr to null, there was an
  // error.
  if (FilenameStart == 0)
    return;

  // Search include directories for this file.
  const DirectoryLookup *CurDir;
  const FileEntry *File = LookupFile(FilenameStart, FilenameEnd,
                                     isAngled, 0, CurDir);
  if (File == 0) {
    Diag(FilenameTok, diag::err_pp_file_not_found)
      << std::string(FilenameStart, FilenameEnd);
    return;
  }

  unsigned FileID = getCurrentFileLexer()->getFileID();
  const FileEntry *CurFile = SourceMgr.getFileEntryForID(FileID);

  // If this file is older than the file it depends on, emit a diagnostic.
  if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
    // Lex tokens at the end of the message and include them in the message.
    std::string Message;
    Lex(DependencyTok);
    while (DependencyTok.isNot(tok::eom)) {
      Message += getSpelling(DependencyTok) + " ";
      Lex(DependencyTok);
    }

    Message.erase(Message.end()-1);
    Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
  }
}

/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
/// If 'Namespace' is non-null, then it is a token required to exist on the
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
void Preprocessor::AddPragmaHandler(const char *Namespace,
                                    PragmaHandler *Handler) {
  PragmaNamespace *InsertNS = PragmaHandlers;

  // If this is specified to be in a namespace, step down into it.
  if (Namespace) {
    IdentifierInfo *NSID = getIdentifierInfo(Namespace);

    // If there is already a pragma handler with the name of this namespace,
    // we either have an error (directive with the same name as a namespace) or
    // we already have the namespace to insert into.
    if (PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID)) {
      InsertNS = Existing->getIfNamespace();
      assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
             " handler with the same name!");
    } else {
      // Otherwise, this namespace doesn't exist yet, create and insert the
      // handler for it.
      InsertNS = new PragmaNamespace(NSID);
      PragmaHandlers->AddPragma(InsertNS);
    }
  }

  // Check to make sure we don't already have a pragma for this identifier.
  assert(!InsertNS->FindHandler(Handler->getName()) &&
         "Pragma handler already exists for this identifier!");
  InsertNS->AddPragma(Handler);
}

/// RemovePragmaHandler - Remove the specific pragma handler from the
/// preprocessor. If \arg Namespace is non-null, then it should be the
/// namespace that \arg Handler was added to. It is an error to remove
/// a handler that has not been registered.
void Preprocessor::RemovePragmaHandler(const char *Namespace,
                                       PragmaHandler *Handler) {
  PragmaNamespace *NS = PragmaHandlers;

  // If this is specified to be in a namespace, step down into it.
  if (Namespace) {
    IdentifierInfo *NSID = getIdentifierInfo(Namespace);
    PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID);
    assert(Existing && "Namespace containing handler does not exist!");

    NS = Existing->getIfNamespace();
    assert(NS && "Invalid namespace, registered as a regular pragma handler!");
  }

  NS->RemovePragmaHandler(Handler);

  // If this is a non-default namespace and it is now empty, remove
  // it.
  if (NS != PragmaHandlers && NS->IsEmpty())
    PragmaHandlers->RemovePragmaHandler(NS);
}

namespace {
/// PragmaOnceHandler - "#pragma once" marks the file as atomically included.
struct PragmaOnceHandler : public PragmaHandler {
  PragmaOnceHandler(const IdentifierInfo *OnceID) : PragmaHandler(OnceID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) {
    PP.CheckEndOfDirective("#pragma once");
    PP.HandlePragmaOnce(OnceTok);
  }
};

/// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the
/// rest of the line is not lexed.
struct PragmaMarkHandler : public PragmaHandler {
  PragmaMarkHandler(const IdentifierInfo *MarkID) : PragmaHandler(MarkID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) {
    PP.HandlePragmaMark();
  }
};

/// PragmaPoisonHandler - "#pragma poison x" marks x as not usable.
struct PragmaPoisonHandler : public PragmaHandler {
  PragmaPoisonHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) {
    PP.HandlePragmaPoison(PoisonTok);
  }
};

/// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file
/// as a system header, which silences warnings in it.
struct PragmaSystemHeaderHandler : public PragmaHandler {
  PragmaSystemHeaderHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &SHToken) {
    PP.HandlePragmaSystemHeader(SHToken);
    PP.CheckEndOfDirective("#pragma");
  }
};
struct PragmaDependencyHandler : public PragmaHandler {
  PragmaDependencyHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &DepToken) {
    PP.HandlePragmaDependency(DepToken);
  }
};
}  // end anonymous namespace

/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
/// #pragma GCC poison/system_header/dependency and #pragma once.
void Preprocessor::RegisterBuiltinPragmas() {
  AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once")));
  AddPragmaHandler(0, new PragmaMarkHandler(getIdentifierInfo("mark")));
  AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
  AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
                                          getIdentifierInfo("system_header")));
  AddPragmaHandler("GCC", new PragmaDependencyHandler(
                                          getIdentifierInfo("dependency")));
}
<commit_msg>Just use the SourceLocation of SysHeaderTok when doing a callback to emit #line information. A diff of the -E output for Cocoa.h shows that there is no change in output.<commit_after>//===--- Pragma.cpp - Pragma registration and handling --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PragmaHandler/PragmaTable interfaces and implements
// pragma related methods of the Preprocessor class.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/Pragma.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;

// Out-of-line destructor to provide a home for the class.
PragmaHandler::~PragmaHandler() {
}

//===----------------------------------------------------------------------===//
// PragmaNamespace Implementation.
//===----------------------------------------------------------------------===//

PragmaNamespace::~PragmaNamespace() {
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i)
    delete Handlers[i];
}

/// FindHandler - Check to see if there is already a handler for the
/// specified name.  If not, return the handler for the null identifier if it
/// exists, otherwise return null.  If IgnoreNull is true (the default) then
/// the null handler isn't returned on failure to match.
PragmaHandler *PragmaNamespace::FindHandler(const IdentifierInfo *Name,
                                            bool IgnoreNull) const {
  PragmaHandler *NullHandler = 0;
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
    if (Handlers[i]->getName() == Name)
      return Handlers[i];

    if (Handlers[i]->getName() == 0)
      NullHandler = Handlers[i];
  }
  return IgnoreNull ? 0 : NullHandler;
}

void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
    if (Handlers[i] == Handler) {
      Handlers[i] = Handlers.back();
      Handlers.pop_back();
      return;
    }
  }
  assert(0 && "Handler not registered in this namespace");
}

void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) {
  // Read the 'namespace' that the directive is in, e.g. STDC.  Do not macro
  // expand it, the user can have a STDC #define, that should not affect this.
  PP.LexUnexpandedToken(Tok);

  // Get the handler for this token.  If there is no handler, ignore the pragma.
  PragmaHandler *Handler = FindHandler(Tok.getIdentifierInfo(), false);
  if (Handler == 0) return;

  // Otherwise, pass it down.
  Handler->HandlePragma(PP, Tok);
}

//===----------------------------------------------------------------------===//
// Preprocessor Pragma Directive Handling.
//===----------------------------------------------------------------------===//

/// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the
/// rest of the pragma, passing it to the registered pragma handlers.
void Preprocessor::HandlePragmaDirective() {
  ++NumPragma;

  // Invoke the first level of pragma handlers which reads the namespace id.
  Token Tok;
  PragmaHandlers->HandlePragma(*this, Tok);

  // If the pragma handler didn't read the rest of the line, consume it now.
  if (CurPPLexer->ParsingPreprocessorDirective)
    DiscardUntilEndOfDirective();
}

/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
/// return the first token after the directive.  The _Pragma token has just
/// been read into 'Tok'.
void Preprocessor::Handle_Pragma(Token &Tok) {
  // Remember the pragma token location.
  SourceLocation PragmaLoc = Tok.getLocation();

  // Read the '('.
  Lex(Tok);
  if (Tok.isNot(tok::l_paren)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // Read the '"..."'.
  Lex(Tok);
  if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // Remember the string.
  std::string StrVal = getSpelling(Tok);
  SourceLocation StrLoc = Tok.getLocation();

  // Read the ')'.
  Lex(Tok);
  if (Tok.isNot(tok::r_paren)) {
    Diag(PragmaLoc, diag::err__Pragma_malformed);
    return;
  }

  // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1.
  if (StrVal[0] == 'L')  // Remove L prefix.
    StrVal.erase(StrVal.begin());
  assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
         "Invalid string token!");

  // Remove the front quote, replacing it with a space, so that the pragma
  // contents appear to have a space before them.
  StrVal[0] = ' ';

  // Replace the terminating quote with a \n\0.
  StrVal[StrVal.size()-1] = '\n';
  StrVal += '\0';

  // Remove escaped quotes and escapes.
  for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
    if (StrVal[i] == '\\' &&
        (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
      // \\ -> '\' and \" -> '"'.
      StrVal.erase(StrVal.begin()+i);
      --e;
    }
  }

  // Plop the string (including the newline and trailing null) into a buffer
  // where we can lex it.
  SourceLocation TokLoc = CreateString(&StrVal[0], StrVal.size(), StrLoc);
  const char *StrData = SourceMgr.getCharacterData(TokLoc);

  // Make and enter a lexer object so that we lex and expand the tokens just
  // like any others.
  Lexer *TL = new Lexer(TokLoc, *this,
                        StrData, StrData+StrVal.size()-1 /* no null */);

  // Ensure that the lexer thinks it is inside a directive, so that end \n will
  // return an EOM token.
  TL->ParsingPreprocessorDirective = true;

  // This lexer really is for _Pragma.
  TL->Is_PragmaLexer = true;

  EnterSourceFileWithLexer(TL, 0);

  // With everything set up, lex this as a #pragma directive.
  HandlePragmaDirective();

  // Finally, return whatever came after the pragma directive.
  return Lex(Tok);
}

/// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
///
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
  if (isInPrimaryFile()) {
    Diag(OnceTok, diag::pp_pragma_once_in_main_file);
    return;
  }

  // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
  unsigned FileID = getCurrentFileLexer()->getFileID();

  // Mark the file as a once-only file now.
  HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForID(FileID));
}

void Preprocessor::HandlePragmaMark() {
  assert(CurPPLexer && "No current lexer?");
  if (CurLexer) CurLexer->ReadToEndOfLine();
  else CurPTHLexer->DiscardToEndOfLine();
}

/// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
///
void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
  Token Tok;

  while (1) {
    // Read the next token to poison.  While doing this, pretend that we are
    // skipping while reading the identifier to poison.
    // This avoids errors on code like:
    //   #pragma GCC poison X
    //   #pragma GCC poison X
    if (CurPPLexer) CurPPLexer->LexingRawMode = true;
    LexUnexpandedToken(Tok);
    if (CurPPLexer) CurPPLexer->LexingRawMode = false;

    // If we reached the end of line, we're done.
    if (Tok.is(tok::eom)) return;

    // Can only poison identifiers.
    if (Tok.isNot(tok::identifier)) {
      Diag(Tok, diag::err_pp_invalid_poison);
      return;
    }

    // Look up the identifier info for the token.  We disabled identifier lookup
    // by saying we're skipping contents, so we need to do this manually.
    IdentifierInfo *II = LookUpIdentifierInfo(Tok);

    // Already poisoned.
    if (II->isPoisoned()) continue;

    // If this is a macro identifier, emit a warning.
    if (II->hasMacroDefinition())
      Diag(Tok, diag::pp_poisoning_existing_macro);

    // Finally, poison it!
    II->setIsPoisoned();
  }
}

/// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
/// that the whole directive has been parsed.
void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
  if (isInPrimaryFile()) {
    Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
    return;
  }

  // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
  PreprocessorLexer *TheLexer = getCurrentFileLexer();

  // Mark the file as a system header.
  const FileEntry *File = SourceMgr.getFileEntryForID(TheLexer->getFileID());
  HeaderInfo.MarkFileSystemHeader(File);

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks)
    Callbacks->FileChanged(SysHeaderTok.getLocation(),
                           PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
}

/// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
///
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
  Token FilenameTok;
  CurPPLexer->LexIncludeFilename(FilenameTok);

  // If the token kind is EOM, the error has already been diagnosed.
  if (FilenameTok.is(tok::eom))
    return;

  // Reserve a buffer to get the spelling.
  llvm::SmallVector<char, 128> FilenameBuffer;
  FilenameBuffer.resize(FilenameTok.getLength());

  const char *FilenameStart = &FilenameBuffer[0];
  unsigned Len = getSpelling(FilenameTok, FilenameStart);
  const char *FilenameEnd = FilenameStart+Len;
  bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(),
                                             FilenameStart, FilenameEnd);
  // If GetIncludeFilenameSpelling set the start ptr to null, there was an
  // error.
  if (FilenameStart == 0)
    return;

  // Search include directories for this file.
  const DirectoryLookup *CurDir;
  const FileEntry *File = LookupFile(FilenameStart, FilenameEnd,
                                     isAngled, 0, CurDir);
  if (File == 0) {
    Diag(FilenameTok, diag::err_pp_file_not_found)
      << std::string(FilenameStart, FilenameEnd);
    return;
  }

  unsigned FileID = getCurrentFileLexer()->getFileID();
  const FileEntry *CurFile = SourceMgr.getFileEntryForID(FileID);

  // If this file is older than the file it depends on, emit a diagnostic.
  if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
    // Lex tokens at the end of the message and include them in the message.
    std::string Message;
    Lex(DependencyTok);
    while (DependencyTok.isNot(tok::eom)) {
      Message += getSpelling(DependencyTok) + " ";
      Lex(DependencyTok);
    }

    Message.erase(Message.end()-1);
    Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
  }
}

/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
/// If 'Namespace' is non-null, then it is a token required to exist on the
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
void Preprocessor::AddPragmaHandler(const char *Namespace,
                                    PragmaHandler *Handler) {
  PragmaNamespace *InsertNS = PragmaHandlers;

  // If this is specified to be in a namespace, step down into it.
  if (Namespace) {
    IdentifierInfo *NSID = getIdentifierInfo(Namespace);

    // If there is already a pragma handler with the name of this namespace,
    // we either have an error (directive with the same name as a namespace) or
    // we already have the namespace to insert into.
    if (PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID)) {
      InsertNS = Existing->getIfNamespace();
      assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
             " handler with the same name!");
    } else {
      // Otherwise, this namespace doesn't exist yet, create and insert the
      // handler for it.
      InsertNS = new PragmaNamespace(NSID);
      PragmaHandlers->AddPragma(InsertNS);
    }
  }

  // Check to make sure we don't already have a pragma for this identifier.
  assert(!InsertNS->FindHandler(Handler->getName()) &&
         "Pragma handler already exists for this identifier!");
  InsertNS->AddPragma(Handler);
}

/// RemovePragmaHandler - Remove the specific pragma handler from the
/// preprocessor. If \arg Namespace is non-null, then it should be the
/// namespace that \arg Handler was added to. It is an error to remove
/// a handler that has not been registered.
void Preprocessor::RemovePragmaHandler(const char *Namespace,
                                       PragmaHandler *Handler) {
  PragmaNamespace *NS = PragmaHandlers;

  // If this is specified to be in a namespace, step down into it.
  if (Namespace) {
    IdentifierInfo *NSID = getIdentifierInfo(Namespace);
    PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID);
    assert(Existing && "Namespace containing handler does not exist!");

    NS = Existing->getIfNamespace();
    assert(NS && "Invalid namespace, registered as a regular pragma handler!");
  }

  NS->RemovePragmaHandler(Handler);

  // If this is a non-default namespace and it is now empty, remove
  // it.
  if (NS != PragmaHandlers && NS->IsEmpty())
    PragmaHandlers->RemovePragmaHandler(NS);
}

namespace {
/// PragmaOnceHandler - "#pragma once" marks the file as atomically included.
struct PragmaOnceHandler : public PragmaHandler {
  PragmaOnceHandler(const IdentifierInfo *OnceID) : PragmaHandler(OnceID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) {
    PP.CheckEndOfDirective("#pragma once");
    PP.HandlePragmaOnce(OnceTok);
  }
};

/// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the
/// rest of the line is not lexed.
struct PragmaMarkHandler : public PragmaHandler {
  PragmaMarkHandler(const IdentifierInfo *MarkID) : PragmaHandler(MarkID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) {
    PP.HandlePragmaMark();
  }
};

/// PragmaPoisonHandler - "#pragma poison x" marks x as not usable.
struct PragmaPoisonHandler : public PragmaHandler {
  PragmaPoisonHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) {
    PP.HandlePragmaPoison(PoisonTok);
  }
};

/// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file
/// as a system header, which silences warnings in it.
struct PragmaSystemHeaderHandler : public PragmaHandler {
  PragmaSystemHeaderHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &SHToken) {
    PP.HandlePragmaSystemHeader(SHToken);
    PP.CheckEndOfDirective("#pragma");
  }
};
struct PragmaDependencyHandler : public PragmaHandler {
  PragmaDependencyHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
  virtual void HandlePragma(Preprocessor &PP, Token &DepToken) {
    PP.HandlePragmaDependency(DepToken);
  }
};
}  // end anonymous namespace

/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
/// #pragma GCC poison/system_header/dependency and #pragma once.
void Preprocessor::RegisterBuiltinPragmas() {
  AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once")));
  AddPragmaHandler(0, new PragmaMarkHandler(getIdentifierInfo("mark")));
  AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
  AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
                                          getIdentifierInfo("system_header")));
  AddPragmaHandler("GCC", new PragmaDependencyHandler(
                                          getIdentifierInfo("dependency")));
}
<|endoftext|>


<commit_before>/// HEADER
#include "apex_ros_interface.h"

/// PROJECT
#include <csapex/utility/register_apex_plugin.h>
#include <csapex_ros/ros_handler.h>
#include "import_ros.h"
#include <csapex/core/drag_io.h>
#include <csapex/model/graph.h>
#include <csapex/model/node_state.h>
#include <csapex/command/add_node.h>
#include <csapex/msg/message_factory.h>
#include <csapex_ros/ros_message_conversion.h>
#include <csapex/msg/generic_value_message.hpp>
#include <csapex_ros/yaml_io.hpp>

/// SYSTEM
#include <boost/regex.hpp>
#include <std_msgs/Int32.h>
#include <std_msgs/Bool.h>
#include <std_msgs/String.h>
#include <std_msgs/Float64.h>
#include <nav_msgs/Odometry.h>
#include <QMimeData>

CSAPEX_REGISTER_CLASS(csapex::APEXRosInterface, csapex::CorePlugin)

using namespace csapex;

namespace {
class RosIoHandler
        : public DragIO::HandlerEnter, public DragIO::HandlerMove, public DragIO::HandlerDrop
{
    static const boost::regex fmt;

    std::string getCmd(QDropEvent* e)
    {
        QByteArray itemData = e->mimeData()->data("application/x-qabstractitemmodeldatalist");
        QDataStream stream(&itemData, QIODevice::ReadOnly);

        int r, c;
        QMap<int, QVariant> v;
        stream >> r >> c >> v;

        return v[Qt::UserRole].toString().toStdString();
    }

    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDragEnterEvent* e) {
        if(e->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
            std::string cmd = getCmd(e);

            bool cmd_could_be_topic = boost::regex_match(cmd, fmt);

            if(cmd_could_be_topic) {
                if(ROSHandler::instance().isConnected() && ROSHandler::instance().topicExists(cmd)) {
                    e->accept();
                    return true;
                }
            }
        }
        return false;
    }
    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDragMoveEvent* e){
        return false;
    }
    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDropEvent* e, const QPointF& scene_pos) {
        if(e->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
            std::string cmd = getCmd(e);

            bool cmd_could_be_topic = boost::regex_match(cmd, fmt);

            if(cmd_could_be_topic) {
                if(ROSHandler::instance().topicExists(cmd)) {
                    QPoint pos = e->pos();

                    UUID uuid = UUID::make(dispatcher->getGraph()->makeUUIDPrefix("csapex::ImportRos"));

                    NodeState::Ptr state(new NodeState(nullptr));
                    ImportRos dummy;
                    dummy.getParameter("topic")->set(cmd);
                    state->setParameterState(dummy.getParameterState());

                    std::string type("csapex::ImportRos");
                    dispatcher->execute(Command::Ptr(new command::AddNode(type, Point(pos.x(), pos.y()), UUID::NONE, uuid, state)));

                    return true;
                }
            }
        }
        return false;
    }
};

const boost::regex RosIoHandler::fmt("[a-zA-Z0-9_\\-/]+");
}

template <typename RosType, typename ApexType>
struct ConvertIntegral
{
    static typename connection_types::GenericValueMessage<ApexType>::Ptr ros2apex(const typename RosType::ConstPtr &ros_msg) {
        typename connection_types::GenericValueMessage<ApexType>::Ptr out(new connection_types::GenericValueMessage<ApexType>);
        out->value = ros_msg->data;
        return out;
    }
    static typename RosType::Ptr apex2ros(const typename connection_types::GenericValueMessage<ApexType>::ConstPtr& apex_msg) {
        typename RosType::Ptr out(new RosType);
        out->data = apex_msg->value;
        return out;
    }
};

APEXRosInterface::APEXRosInterface()
    : core_(nullptr), disabled_(false)
{
}

APEXRosInterface::~APEXRosInterface()
{
}

void APEXRosInterface::prepare(Settings &settings)
{
    ROSHandler::createInstance(settings);
}

void APEXRosInterface::init(CsApexCore &core)
{
    core_ = &core;

    ROSHandler::instance().registerConnectionCallback(std::bind(&APEXRosInterface::registerCommandListener, this));

    RosMessageConversion::registerConversion<std_msgs::Bool, connection_types::GenericValueMessage<bool>, ConvertIntegral<std_msgs::Bool, bool> >();
    RosMessageConversion::registerConversion<std_msgs::Int32, connection_types::GenericValueMessage<int>, ConvertIntegral<std_msgs::Int32, int> >();
    RosMessageConversion::registerConversion<std_msgs::Float64, connection_types::GenericValueMessage<double>, ConvertIntegral<std_msgs::Float64, double> >();
    RosMessageConversion::registerConversion<std_msgs::String, connection_types::GenericValueMessage<std::string>, ConvertIntegral<std_msgs::String, std::string> >();

    RosMessageConversionT<nav_msgs::Odometry>::registerConversion();
    RosMessageConversionT<geometry_msgs::PoseStamped>::registerConversion();
    RosMessageConversionT<visualization_msgs::MarkerArray>::registerConversion();
    RosMessageConversionT<visualization_msgs::Marker>::registerConversion();
}

void APEXRosInterface::registerCommandListener()
{
    assert(ROSHandler::instance().isConnected());
    global_command_sub_ = ROSHandler::instance().nh()->subscribe
            <std_msgs::String>("/syscommand", 10, std::bind(&APEXRosInterface::command, this, std::placeholders::_1, true));
    private_command_sub_ = ROSHandler::instance().nh()->subscribe
            <std_msgs::String>("command", 10, std::bind(&APEXRosInterface::command, this, std::placeholders::_1, false));

    ros::spinOnce();
}

void APEXRosInterface::initUI(DragIO &dragio)
{
    dragio.registerHandler<RosIoHandler>();
}

void APEXRosInterface::command(const std_msgs::StringConstPtr& cmd, bool global_cmd)
{
    std::string command = cmd->data;
    bool local_cmd = !global_cmd;

    /*
     * pause / unpause:
     *   - temporary disable everything to conserve computational power
     *   - globally accepted, if this node is not disabled
     *
     * stop / resume
     *   - completely disable / enable this subsystem, when it is not needed
     *   - only locally accepted
     *   - overwrites pause -> a disabled instance cannot be unpaused
     */

    if(!disabled_) {
        // disabled state is stronger than pause / unpause
        if(command == "pause") {
            core_->setPause(true);

        } else if(command == "unpause"){
            core_->setPause(false);
        }
    }

    if(local_cmd) {
        if(command == "stop") {
            disabled_ = true;
            core_->setPause(true);
        } else if(command == "resume") {
            disabled_ = false;
            core_->setPause(false);
        }
    }
}

void APEXRosInterface::shutdown()
{
    ROSHandler::instance().stop();
}
<commit_msg>moved occupancy grid registration<commit_after>/// HEADER
#include "apex_ros_interface.h"

/// PROJECT
#include <csapex/utility/register_apex_plugin.h>
#include <csapex_ros/ros_handler.h>
#include "import_ros.h"
#include <csapex/core/drag_io.h>
#include <csapex/model/graph.h>
#include <csapex/model/node_state.h>
#include <csapex/command/add_node.h>
#include <csapex/msg/message_factory.h>
#include <csapex_ros/ros_message_conversion.h>
#include <csapex/msg/generic_value_message.hpp>
#include <csapex_ros/yaml_io.hpp>

/// SYSTEM
#include <boost/regex.hpp>
#include <std_msgs/Int32.h>
#include <std_msgs/Bool.h>
#include <std_msgs/String.h>
#include <std_msgs/Float64.h>
#include <nav_msgs/Odometry.h>
#include <QMimeData>

CSAPEX_REGISTER_CLASS(csapex::APEXRosInterface, csapex::CorePlugin)

using namespace csapex;

namespace {
class RosIoHandler
        : public DragIO::HandlerEnter, public DragIO::HandlerMove, public DragIO::HandlerDrop
{
    static const boost::regex fmt;

    std::string getCmd(QDropEvent* e)
    {
        QByteArray itemData = e->mimeData()->data("application/x-qabstractitemmodeldatalist");
        QDataStream stream(&itemData, QIODevice::ReadOnly);

        int r, c;
        QMap<int, QVariant> v;
        stream >> r >> c >> v;

        return v[Qt::UserRole].toString().toStdString();
    }

    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDragEnterEvent* e) {
        if(e->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
            std::string cmd = getCmd(e);

            bool cmd_could_be_topic = boost::regex_match(cmd, fmt);

            if(cmd_could_be_topic) {
                if(ROSHandler::instance().isConnected() && ROSHandler::instance().topicExists(cmd)) {
                    e->accept();
                    return true;
                }
            }
        }
        return false;
    }
    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDragMoveEvent* e){
        return false;
    }
    virtual bool handle(CommandDispatcher* dispatcher, QWidget *src, QDropEvent* e, const QPointF& scene_pos) {
        if(e->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
            std::string cmd = getCmd(e);

            bool cmd_could_be_topic = boost::regex_match(cmd, fmt);

            if(cmd_could_be_topic) {
                if(ROSHandler::instance().topicExists(cmd)) {
                    QPoint pos = e->pos();

                    UUID uuid = UUID::make(dispatcher->getGraph()->makeUUIDPrefix("csapex::ImportRos"));

                    NodeState::Ptr state(new NodeState(nullptr));
                    ImportRos dummy;
                    dummy.getParameter("topic")->set(cmd);
                    state->setParameterState(dummy.getParameterState());

                    std::string type("csapex::ImportRos");
                    dispatcher->execute(Command::Ptr(new command::AddNode(type, Point(pos.x(), pos.y()), UUID::NONE, uuid, state)));

                    return true;
                }
            }
        }
        return false;
    }
};

const boost::regex RosIoHandler::fmt("[a-zA-Z0-9_\\-/]+");
}

template <typename RosType, typename ApexType>
struct ConvertIntegral
{
    static typename connection_types::GenericValueMessage<ApexType>::Ptr ros2apex(const typename RosType::ConstPtr &ros_msg) {
        typename connection_types::GenericValueMessage<ApexType>::Ptr out(new connection_types::GenericValueMessage<ApexType>);
        out->value = ros_msg->data;
        return out;
    }
    static typename RosType::Ptr apex2ros(const typename connection_types::GenericValueMessage<ApexType>::ConstPtr& apex_msg) {
        typename RosType::Ptr out(new RosType);
        out->data = apex_msg->value;
        return out;
    }
};

APEXRosInterface::APEXRosInterface()
    : core_(nullptr), disabled_(false)
{
}

APEXRosInterface::~APEXRosInterface()
{
}

void APEXRosInterface::prepare(Settings &settings)
{
    ROSHandler::createInstance(settings);
}

void APEXRosInterface::init(CsApexCore &core)
{
    core_ = &core;

    ROSHandler::instance().registerConnectionCallback(std::bind(&APEXRosInterface::registerCommandListener, this));

    RosMessageConversion::registerConversion<std_msgs::Bool, connection_types::GenericValueMessage<bool>, ConvertIntegral<std_msgs::Bool, bool> >();
    RosMessageConversion::registerConversion<std_msgs::Int32, connection_types::GenericValueMessage<int>, ConvertIntegral<std_msgs::Int32, int> >();
    RosMessageConversion::registerConversion<std_msgs::Float64, connection_types::GenericValueMessage<double>, ConvertIntegral<std_msgs::Float64, double> >();
    RosMessageConversion::registerConversion<std_msgs::String, connection_types::GenericValueMessage<std::string>, ConvertIntegral<std_msgs::String, std::string> >();

    RosMessageConversionT<nav_msgs::Odometry>::registerConversion();
    RosMessageConversionT<geometry_msgs::PoseStamped>::registerConversion();
    RosMessageConversionT<visualization_msgs::MarkerArray>::registerConversion();
    RosMessageConversionT<visualization_msgs::Marker>::registerConversion();
    RosMessageConversionT<nav_msgs::OccupancyGrid>::registerConversion();
}

void APEXRosInterface::registerCommandListener()
{
    assert(ROSHandler::instance().isConnected());
    global_command_sub_ = ROSHandler::instance().nh()->subscribe
            <std_msgs::String>("/syscommand", 10, std::bind(&APEXRosInterface::command, this, std::placeholders::_1, true));
    private_command_sub_ = ROSHandler::instance().nh()->subscribe
            <std_msgs::String>("command", 10, std::bind(&APEXRosInterface::command, this, std::placeholders::_1, false));

    ros::spinOnce();
}

void APEXRosInterface::initUI(DragIO &dragio)
{
    dragio.registerHandler<RosIoHandler>();
}

void APEXRosInterface::command(const std_msgs::StringConstPtr& cmd, bool global_cmd)
{
    std::string command = cmd->data;
    bool local_cmd = !global_cmd;

    /*
     * pause / unpause:
     *   - temporary disable everything to conserve computational power
     *   - globally accepted, if this node is not disabled
     *
     * stop / resume
     *   - completely disable / enable this subsystem, when it is not needed
     *   - only locally accepted
     *   - overwrites pause -> a disabled instance cannot be unpaused
     */

    if(!disabled_) {
        // disabled state is stronger than pause / unpause
        if(command == "pause") {
            core_->setPause(true);

        } else if(command == "unpause"){
            core_->setPause(false);
        }
    }

    if(local_cmd) {
        if(command == "stop") {
            disabled_ = true;
            core_->setPause(true);
        } else if(command == "resume") {
            disabled_ = false;
            core_->setPause(false);
        }
    }
}

void APEXRosInterface::shutdown()
{
    ROSHandler::instance().stop();
}
<|endoftext|>