<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017-2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "us_ticker_api.h"
#include "BLE.h"
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_os.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "hci_drv.h"
#include "CordioBLE.h"
#include "mbed_assert.h"

#include "CordioPalAttClient.h"
#include "CordioPalSecurityManager.h"

/*! WSF handler ID */
wsfHandlerId_t stack_handler_id;

/**
 * Weak definition of ble_cordio_get_hci_driver.
 * A runtime error is generated if the user does not define any
 * ble_cordio_get_hci_driver.
 */
MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver()
{
    error("Please provide an implementation for the HCI driver");
    ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL;
    return *bad_instance;
}

/**
 * Low level HCI interface between Cordio stack and the port.
 */
extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData)
{
    return ble_cordio_get_hci_driver().write(type, len, pData);
}

extern "C" void hci_mbed_os_start_reset_sequence(void)
{
    ble_cordio_get_hci_driver().start_reset_sequence();
}

extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg)
{
     ble_cordio_get_hci_driver().handle_reset_sequence(msg);
}

/*
 * This function will signal to the user code by calling signalEventsToProcess.
 * It is registered and called into the Wsf Stack.
 */
extern "C" void wsf_mbed_ble_signal_event(void)
{
    ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE);
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *createBLEInstance()
{
    return (&(ble::vendor::cordio::BLE::deviceInstance()));
}

namespace ble {
namespace vendor {
namespace cordio {

BLE::BLE(CordioHCIDriver& hci_driver) :
    initialization_status(NOT_INITIALIZED),
    instanceID(::BLE::DEFAULT_INSTANCE),
    _event_queue()
{
    _hci_driver = &hci_driver;
    stack_setup();
}

BLE::~BLE() { }

/**
 * The singleton which represents the BLE transport for the BLE.
 */
BLE& BLE::deviceInstance()
{
    static BLE instance(
        ble_cordio_get_hci_driver()
    );
    return instance;
}

ble_error_t BLE::init(
    ::BLE::InstanceID_t instanceID,
    FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback)
{
    switch (initialization_status) {
        case NOT_INITIALIZED:
            _event_queue.initialize(this, instanceID);
            _init_callback = initCallback;
            start_stack_reset();
            return BLE_ERROR_NONE;

        case INITIALIZING:
            return BLE_ERROR_INITIALIZATION_INCOMPLETE;

        case INITIALIZED:
            return BLE_ERROR_NONE;

        default:
            return BLE_ERROR_UNSPECIFIED;
    }
}

bool BLE::hasInitialized() const
{
    return initialization_status == INITIALIZED;
}

ble_error_t BLE::shutdown()
{
    if (initialization_status != INITIALIZED) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    initialization_status = NOT_INITIALIZED;
    _hci_driver->terminate();

    getGattServer().reset();
    getGattClient().reset();
    getGap().reset();
    _event_queue.clear();

    return BLE_ERROR_NONE;
}

const char* BLE::getVersion()
{
    static const char version[] = "generic-cordio";
    return version;
}

generic::GenericGap& BLE::getGap()
{
    static pal::vendor::cordio::GenericAccessService cordio_gap_service;
    static ble::generic::GenericGap gap(
        _event_queue,
        pal::vendor::cordio::Gap::get_gap(),
        cordio_gap_service
    );

    return gap;
}

const generic::GenericGap& BLE::getGap() const
{
    BLE &self = const_cast<BLE&>(*this);
    return const_cast<const generic::GenericGap&>(self.getGap());
};

GattServer& BLE::getGattServer()
{
    return cordio::GattServer::getInstance();
}

const GattServer& BLE::getGattServer() const
{
    return cordio::GattServer::getInstance();
}

generic::GenericGattClient& BLE::getGattClient()
{
    static pal::AttClientToGattClientAdapter pal_client(
        pal::vendor::cordio::CordioAttClient::get_client()
    );
    static generic::GenericGattClient client(&pal_client);

    return client;
}

SecurityManager& BLE::getSecurityManager()
{
    static pal::MemorySecurityDb m_db;
    static SigningEventMonitorProxy signing_event_monitor(*this);
    static generic::GenericSecurityManager m_instance(
        pal::vendor::cordio::CordioSecurityManager::get_security_manager(),
        m_db,
        getGap(),
        signing_event_monitor
    );

    return m_instance;
}

const SecurityManager& BLE::getSecurityManager() const
{
    const BLE &self = const_cast<BLE&>(*this);
    return const_cast<const SecurityManager&>(self.getSecurityManager());
}

void BLE::waitForEvent()
{
    static Timeout nextTimeout;
    timestamp_t nextTimestamp;
    bool_t pTimerRunning;

    callDispatcher();

    if (wsfOsReadyToSleep()) {
        // setup an mbed timer for the next cordio timeout
        nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

void BLE::processEvents()
{
    callDispatcher();
}

 void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg)
 {
    if (msg == NULL) {
        return;
    }

    if (ble::pal::vendor::cordio::CordioSecurityManager::get_security_manager().sm_handler(msg)) {
        return;
    }

    switch(msg->event) {
        case DM_RESET_CMPL_IND: {
            ::BLE::InitializationCompleteCallbackContext context = {
                ::BLE::Instance(::BLE::DEFAULT_INSTANCE),
                BLE_ERROR_NONE
            };
            deviceInstance().getGattServer().initialize();
            deviceInstance().initialization_status = INITIALIZED;
            _init_callback.call(&context);
        }   break;

        default:
            ble::pal::vendor::cordio::Gap::gap_handler(msg);
            break;
    }
}

void BLE::device_manager_cb(dmEvt_t* dm_event)
{
    BLE::deviceInstance().stack_handler(0, &dm_event->hdr);
}

/*
 * AttServerInitDeInitCback callback is used to Initialize/Deinitialize
 * the CCC Table of the ATT Server when a remote peer requests to Open
 * or Close the connection.
 */
 void BLE::connection_handler(dmEvt_t* dm_event)
 {
    dmConnId_t connId = (dmConnId_t)dm_event->hdr.param;

    switch (dm_event->hdr.event) {
        case DM_CONN_OPEN_IND:
            /* set up CCC table with uninitialized (all zero) values */
            AttsCccInitTable(connId, NULL);
            break;
        case DM_CONN_CLOSE_IND:
            /* clear CCC table on connection close */
            AttsCccClearTable(connId);
            break;
        default:
            break;
    }
}

void BLE::timeoutCallback()
{
    wsf_mbed_ble_signal_event();
}

void BLE::stack_setup()
{
    MBED_ASSERT(_hci_driver != NULL);

    wsfHandlerId_t handlerId;

    buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();

    // Initialize buffers with the ones provided by the HCI driver
    uint16_t bytes_used = WsfBufInit(
        buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory,
        buf_pool_desc.pool_count, buf_pool_desc.pool_description
    );

    MBED_ASSERT(bytes_used != 0);

    WsfTimerInit();
    SecInit();

    // Note: enable once security is supported
    SecRandInit();
    SecAesInit();
    SecCmacInit();
    SecEccInit();

    handlerId = WsfOsSetNextHandler(HciHandler);
    HciHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(DmHandler);
    DmAdvInit();
    DmScanInit();
    DmConnInit();
    DmConnMasterInit();
    DmConnSlaveInit();
    DmSecInit();

    // Note: enable once security is supported
    DmSecLescInit();
    DmPrivInit();
    DmHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
    L2cSlaveHandlerInit(handlerId);
    L2cInit();
    L2cSlaveInit();
    L2cMasterInit();

    handlerId = WsfOsSetNextHandler(AttHandler);
    AttHandlerInit(handlerId);
    AttsInit();
    AttsIndInit();
    AttcInit();

    handlerId = WsfOsSetNextHandler(SmpHandler);
    SmpHandlerInit(handlerId);
    SmprInit();
    SmprScInit();
    SmpiInit();
    SmpiScInit();

    stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler);

    HciSetMaxRxAclLen(100);

    DmRegister(BLE::device_manager_cb);
    DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb);
    AttConnRegister(BLE::connection_handler);
    AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler);
}

void BLE::start_stack_reset()
{
    _hci_driver->initialize();
    DmDevReset();
}

void BLE::callDispatcher()
{
    // process the external event queue
    _event_queue.process();

    // follow by stack events
    static uint32_t lastTimeUs = us_ticker_read();
    uint32_t currTimeUs, deltaTimeMs;

    // Update the current cordio time
    currTimeUs = us_ticker_read();
    deltaTimeMs = (currTimeUs - lastTimeUs) / 1000;
    if (deltaTimeMs > 0) {
        WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK);
        lastTimeUs += deltaTimeMs * 1000;
    }

    wsfOsDispatcher();

    if (wsfOsReadyToSleep()) {
        static Timeout nextTimeout;
        // setup an mbed timer for the next Cordio timeout
        bool_t pTimerRunning;
        timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

CordioHCIDriver* BLE::_hci_driver = NULL;

FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback;

} // namespace cordio
} // namespace vendor
} // namespace ble
<commit_msg>Cordio: Enable client and server signing<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017-2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "us_ticker_api.h"
#include "BLE.h"
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_os.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "hci_drv.h"
#include "CordioBLE.h"
#include "mbed_assert.h"

#include "CordioPalAttClient.h"
#include "CordioPalSecurityManager.h"

/*! WSF handler ID */
wsfHandlerId_t stack_handler_id;

/**
 * Weak definition of ble_cordio_get_hci_driver.
 * A runtime error is generated if the user does not define any
 * ble_cordio_get_hci_driver.
 */
MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver()
{
    error("Please provide an implementation for the HCI driver");
    ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL;
    return *bad_instance;
}

/**
 * Low level HCI interface between Cordio stack and the port.
 */
extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData)
{
    return ble_cordio_get_hci_driver().write(type, len, pData);
}

extern "C" void hci_mbed_os_start_reset_sequence(void)
{
    ble_cordio_get_hci_driver().start_reset_sequence();
}

extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg)
{
     ble_cordio_get_hci_driver().handle_reset_sequence(msg);
}

/*
 * This function will signal to the user code by calling signalEventsToProcess.
 * It is registered and called into the Wsf Stack.
 */
extern "C" void wsf_mbed_ble_signal_event(void)
{
    ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE);
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *createBLEInstance()
{
    return (&(ble::vendor::cordio::BLE::deviceInstance()));
}

namespace ble {
namespace vendor {
namespace cordio {

BLE::BLE(CordioHCIDriver& hci_driver) :
    initialization_status(NOT_INITIALIZED),
    instanceID(::BLE::DEFAULT_INSTANCE),
    _event_queue()
{
    _hci_driver = &hci_driver;
    stack_setup();
}

BLE::~BLE() { }

/**
 * The singleton which represents the BLE transport for the BLE.
 */
BLE& BLE::deviceInstance()
{
    static BLE instance(
        ble_cordio_get_hci_driver()
    );
    return instance;
}

ble_error_t BLE::init(
    ::BLE::InstanceID_t instanceID,
    FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback)
{
    switch (initialization_status) {
        case NOT_INITIALIZED:
            _event_queue.initialize(this, instanceID);
            _init_callback = initCallback;
            start_stack_reset();
            return BLE_ERROR_NONE;

        case INITIALIZING:
            return BLE_ERROR_INITIALIZATION_INCOMPLETE;

        case INITIALIZED:
            return BLE_ERROR_NONE;

        default:
            return BLE_ERROR_UNSPECIFIED;
    }
}

bool BLE::hasInitialized() const
{
    return initialization_status == INITIALIZED;
}

ble_error_t BLE::shutdown()
{
    if (initialization_status != INITIALIZED) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    initialization_status = NOT_INITIALIZED;
    _hci_driver->terminate();

    getGattServer().reset();
    getGattClient().reset();
    getGap().reset();
    _event_queue.clear();

    return BLE_ERROR_NONE;
}

const char* BLE::getVersion()
{
    static const char version[] = "generic-cordio";
    return version;
}

generic::GenericGap& BLE::getGap()
{
    static pal::vendor::cordio::GenericAccessService cordio_gap_service;
    static ble::generic::GenericGap gap(
        _event_queue,
        pal::vendor::cordio::Gap::get_gap(),
        cordio_gap_service
    );

    return gap;
}

const generic::GenericGap& BLE::getGap() const
{
    BLE &self = const_cast<BLE&>(*this);
    return const_cast<const generic::GenericGap&>(self.getGap());
};

GattServer& BLE::getGattServer()
{
    return cordio::GattServer::getInstance();
}

const GattServer& BLE::getGattServer() const
{
    return cordio::GattServer::getInstance();
}

generic::GenericGattClient& BLE::getGattClient()
{
    static pal::AttClientToGattClientAdapter pal_client(
        pal::vendor::cordio::CordioAttClient::get_client()
    );
    static generic::GenericGattClient client(&pal_client);

    return client;
}

SecurityManager& BLE::getSecurityManager()
{
    static pal::MemorySecurityDb m_db;
    static SigningEventMonitorProxy signing_event_monitor(*this);
    static generic::GenericSecurityManager m_instance(
        pal::vendor::cordio::CordioSecurityManager::get_security_manager(),
        m_db,
        getGap(),
        signing_event_monitor
    );

    return m_instance;
}

const SecurityManager& BLE::getSecurityManager() const
{
    const BLE &self = const_cast<BLE&>(*this);
    return const_cast<const SecurityManager&>(self.getSecurityManager());
}

void BLE::waitForEvent()
{
    static Timeout nextTimeout;
    timestamp_t nextTimestamp;
    bool_t pTimerRunning;

    callDispatcher();

    if (wsfOsReadyToSleep()) {
        // setup an mbed timer for the next cordio timeout
        nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

void BLE::processEvents()
{
    callDispatcher();
}

 void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg)
 {
    if (msg == NULL) {
        return;
    }

    if (ble::pal::vendor::cordio::CordioSecurityManager::get_security_manager().sm_handler(msg)) {
        return;
    }

    switch(msg->event) {
        case DM_RESET_CMPL_IND: {
            ::BLE::InitializationCompleteCallbackContext context = {
                ::BLE::Instance(::BLE::DEFAULT_INSTANCE),
                BLE_ERROR_NONE
            };
            deviceInstance().getGattServer().initialize();
            deviceInstance().initialization_status = INITIALIZED;
            _init_callback.call(&context);
        }   break;

        default:
            ble::pal::vendor::cordio::Gap::gap_handler(msg);
            break;
    }
}

void BLE::device_manager_cb(dmEvt_t* dm_event)
{
    BLE::deviceInstance().stack_handler(0, &dm_event->hdr);
}

/*
 * AttServerInitDeInitCback callback is used to Initialize/Deinitialize
 * the CCC Table of the ATT Server when a remote peer requests to Open
 * or Close the connection.
 */
 void BLE::connection_handler(dmEvt_t* dm_event)
 {
    dmConnId_t connId = (dmConnId_t)dm_event->hdr.param;

    switch (dm_event->hdr.event) {
        case DM_CONN_OPEN_IND:
            /* set up CCC table with uninitialized (all zero) values */
            AttsCccInitTable(connId, NULL);
            break;
        case DM_CONN_CLOSE_IND:
            /* clear CCC table on connection close */
            AttsCccClearTable(connId);
            break;
        default:
            break;
    }
}

void BLE::timeoutCallback()
{
    wsf_mbed_ble_signal_event();
}

void BLE::stack_setup()
{
    MBED_ASSERT(_hci_driver != NULL);

    wsfHandlerId_t handlerId;

    buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();

    // Initialize buffers with the ones provided by the HCI driver
    uint16_t bytes_used = WsfBufInit(
        buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory,
        buf_pool_desc.pool_count, buf_pool_desc.pool_description
    );

    MBED_ASSERT(bytes_used != 0);

    WsfTimerInit();
    SecInit();

    // Note: enable once security is supported
    SecRandInit();
    SecAesInit();
    SecCmacInit();
    SecEccInit();

    handlerId = WsfOsSetNextHandler(HciHandler);
    HciHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(DmHandler);
    DmAdvInit();
    DmScanInit();
    DmConnInit();
    DmConnMasterInit();
    DmConnSlaveInit();
    DmSecInit();

    // Note: enable once security is supported
    DmSecLescInit();
    DmPrivInit();
    DmHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
    L2cSlaveHandlerInit(handlerId);
    L2cInit();
    L2cSlaveInit();
    L2cMasterInit();

    handlerId = WsfOsSetNextHandler(AttHandler);
    AttHandlerInit(handlerId);
    AttsInit();
    AttsIndInit();
    AttsSignInit();
    AttcInit();
    AttcSignInit();

    handlerId = WsfOsSetNextHandler(SmpHandler);
    SmpHandlerInit(handlerId);
    SmprInit();
    SmprScInit();
    SmpiInit();
    SmpiScInit();

    stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler);

    HciSetMaxRxAclLen(100);

    DmRegister(BLE::device_manager_cb);
    DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb);
    AttConnRegister(BLE::connection_handler);
    AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler);
}

void BLE::start_stack_reset()
{
    _hci_driver->initialize();
    DmDevReset();
}

void BLE::callDispatcher()
{
    // process the external event queue
    _event_queue.process();

    // follow by stack events
    static uint32_t lastTimeUs = us_ticker_read();
    uint32_t currTimeUs, deltaTimeMs;

    // Update the current cordio time
    currTimeUs = us_ticker_read();
    deltaTimeMs = (currTimeUs - lastTimeUs) / 1000;
    if (deltaTimeMs > 0) {
        WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK);
        lastTimeUs += deltaTimeMs * 1000;
    }

    wsfOsDispatcher();

    if (wsfOsReadyToSleep()) {
        static Timeout nextTimeout;
        // setup an mbed timer for the next Cordio timeout
        bool_t pTimerRunning;
        timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

CordioHCIDriver* BLE::_hci_driver = NULL;

FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback;

} // namespace cordio
} // namespace vendor
} // namespace ble
<|endoftext|>


<commit_before>Matrix3i m = Matrix3i::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is m.minor(1,1):" << endl << m.minor(1,1) << endl;
<commit_msg>Remove doc/snippets/MatrixBase_minor.cpp because minor() was removed.<commit_after><|endoftext|>


<commit_before>/*
 * TemplateComponent.cpp
 *
 *  Created on: Jan 23, 2014
 *      Author: gwue
 */

#include "TemplateSoundComponent.hpp"

// include the concrete implementation headers.
#include "impl/TemplateSoundComponent_SW.hpp"
// #include "impl/TemplateSoundComponent_HW.hpp"

// Macro to define the Component name. This will be the name that will later appear in the TGF files
DEFINE_COMPONENTNAME(TemplateSoundComponent, "template")

// Export the sound compononent such that it can be compiled as a shared object
// Different possibilities here:
// EXPORT_SOUNDCOMPONENT_MIXED_IMPL(CLASSNAME) --> both HW and SW implementations exist
// EXPORT_SOUNDCOMPONENT_SW_ONLY(CLASSNAME)
// EXPORT_SOUNDCOMPONENT_HW_ONLY(CLASSNAME)
// EXPORT_SOUNDCOMPONENT_NO_IMPL(CLASSNAME) --> no impl/ subclass, processing is done right here.
//												can be used for very simple stuff like constants.
//												preferably use SW_ONLY instead

EXPORT_SOUNDCOMPONENT_SW_ONLY(TemplateSoundComponent);

TemplateSoundComponent::TemplateSoundComponent(std::vector<std::string> params) :
		SoundComponentImpl(params)
{
	// Read some value from the first parameter
	std::stringstream str;
	str << params[0];
	int someValue;
	str >> someValue;

	// Register ports (that you have declared in the header file)
	// CREATE_AND_REGISTER_PORT3(<ComponentClass>, In|Out, SoundPort|ControlPort, <Name>, <Portumber>
	// <ComponentClass> is the name of this component
	// Either In or Out to specify the direction of this port
	// Type of the Port
	// <Name> as defined in the header
	// <Portnumber> as defined in the header

	// For: DECLARE_PORT3(ControlPort, TemplateControlIn, 1);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, In, ControlPort, TemplateControlIn, 1);

	// For: DECLARE_PORT3(ControlPort, TemplateControlOut, 1);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, In, ControlPort, TemplateControlOut, 1);

	// For: DECLARE_PORT3(SoundPort, TemplateSoundIn, 2);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, In, SoundPort, TemplateSoundIn, 2);

	// For: DECLARE_PORT3(SoundPort, TemplateSoundOut, 2);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, Out, SoundPort, TemplateSoundOut, 2);
}

TemplateSoundComponent::~TemplateSoundComponent(){}

void TemplateSoundComponent::init()
{
	// You can init() sound output ports to clear their buffers
	m_TemplateSoundOut_2_Port->init();
}

// ::process is not implemented here but in the SW subclass!
<commit_msg>Fixed a small error in the template (Out Port that was declared as In)<commit_after>/*
 * TemplateComponent.cpp
 *
 *  Created on: Jan 23, 2014
 *      Author: gwue
 */

#include "TemplateSoundComponent.hpp"

// include the concrete implementation headers.
#include "impl/TemplateSoundComponent_SW.hpp"
// #include "impl/TemplateSoundComponent_HW.hpp"

// Macro to define the Component name. This will be the name that will later appear in the TGF files
DEFINE_COMPONENTNAME(TemplateSoundComponent, "template")

// Export the sound compononent such that it can be compiled as a shared object
// Different possibilities here:
// EXPORT_SOUNDCOMPONENT_MIXED_IMPL(CLASSNAME) --> both HW and SW implementations exist
// EXPORT_SOUNDCOMPONENT_SW_ONLY(CLASSNAME)
// EXPORT_SOUNDCOMPONENT_HW_ONLY(CLASSNAME)
// EXPORT_SOUNDCOMPONENT_NO_IMPL(CLASSNAME) --> no impl/ subclass, processing is done right here.
//												can be used for very simple stuff like constants.
//												preferably use SW_ONLY instead

EXPORT_SOUNDCOMPONENT_SW_ONLY(TemplateSoundComponent);

TemplateSoundComponent::TemplateSoundComponent(std::vector<std::string> params) :
		SoundComponentImpl(params)
{
	// Read some value from the first parameter
	std::stringstream str;
	str << params[0];
	int someValue;
	str >> someValue;

	// Register ports (that you have declared in the header file)
	// CREATE_AND_REGISTER_PORT3(<ComponentClass>, In|Out, SoundPort|ControlPort, <Name>, <Portumber>
	// <ComponentClass> is the name of this component
	// Either In or Out to specify the direction of this port
	// Type of the Port
	// <Name> as defined in the header
	// <Portnumber> as defined in the header

	// For: DECLARE_PORT3(ControlPort, TemplateControlIn, 1);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, In, ControlPort, TemplateControlIn, 1);

	// For: DECLARE_PORT3(ControlPort, TemplateControlOut, 1);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, Out, ControlPort, TemplateControlOut, 1);

	// For: DECLARE_PORT3(SoundPort, TemplateSoundIn, 2);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, In, SoundPort, TemplateSoundIn, 2);

	// For: DECLARE_PORT3(SoundPort, TemplateSoundOut, 2);
	CREATE_AND_REGISTER_PORT3(TemplateSoundComponent, Out, SoundPort, TemplateSoundOut, 2);
}

TemplateSoundComponent::~TemplateSoundComponent(){}

void TemplateSoundComponent::init()
{
	// You can init() sound output ports to clear their buffers
	m_TemplateSoundOut_2_Port->init();
}

// ::process is not implemented here but in the SW subclass!
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/menu_gtk.h"

#include "app/gfx/gtk_util.h"
#include "app/l10n_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "chrome/browser/gtk/standard_menus.h"
#include "chrome/common/gtk_util.h"
#include "third_party/skia/include/core/SkBitmap.h"

using gtk_util::ConvertAcceleratorsFromWindowsStyle;

bool MenuGtk::block_activation_ = false;

MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
                 const MenuCreateMaterial* menu_data,
                 GtkAccelGroup* accel_group)
    : delegate_(delegate),
      dummy_accel_group_(gtk_accel_group_new()),
      menu_(gtk_menu_new()),
      factory_(this) {
  ConnectSignalHandlers();
  BuildMenuIn(menu_.get(), menu_data, accel_group);
}

MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, bool load)
    : delegate_(delegate),
      dummy_accel_group_(NULL),
      menu_(gtk_menu_new()),
      factory_(this) {
  ConnectSignalHandlers();
  if (load)
    BuildMenuFromDelegate();
}

MenuGtk::~MenuGtk() {
  menu_.Destroy();
  STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
  if (dummy_accel_group_)
    g_object_unref(dummy_accel_group_);
}

void MenuGtk::ConnectSignalHandlers() {
  // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
  // take a long time or even start a nested message loop.
  g_signal_connect(menu_.get(), "show", G_CALLBACK(OnMenuShow), this);
  g_signal_connect(menu_.get(), "hide", G_CALLBACK(OnMenuHidden), this);
}

void MenuGtk::AppendMenuItemWithLabel(int command_id,
                                      const std::string& label) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_menu_item_new_with_mnemonic(converted_label.c_str());
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendMenuItemWithIcon(int command_id,
                                     const std::string& label,
                                     const SkBitmap& icon) {
  GtkWidget* menu_item = BuildMenuItemWithImage(label, icon);
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendCheckMenuItemWithLabel(int command_id,
                                           const std::string& label) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_check_menu_item_new_with_mnemonic(converted_label.c_str());
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendSeparator() {
  GtkWidget* menu_item = gtk_separator_menu_item_new();
  gtk_widget_show(menu_item);
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_.get()), menu_item);
}

void MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
  g_object_set_data(G_OBJECT(menu_item), "menu-id",
                    reinterpret_cast<void*>(command_id));

  g_signal_connect(G_OBJECT(menu_item), "activate",
                   G_CALLBACK(OnMenuItemActivated), this);

  gtk_widget_show(menu_item);
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_.get()), menu_item);
}

void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
  DCHECK(event->type == GDK_BUTTON_PRESS)
      << "Non-button press event sent to RunMenuAt";

  GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
  Popup(widget, event_button->button, event_button->time);
}

void MenuGtk::Popup(GtkWidget* widget, gint button_type, guint32 timestamp) {
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL,
                 WidgetMenuPositionFunc,
                 widget,
                 button_type, timestamp);
}

void MenuGtk::PopupAsContext(guint32 event_time) {
  // TODO(estade): |button| value of 3 (6th argument) is not strictly true,
  // but does it matter?
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL, NULL, NULL, 3, event_time);
}

void MenuGtk::PopupAsContextAt(guint32 event_time, gfx::Point point) {
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL,
                 PointMenuPositionFunc, &point, 3, event_time);
}

void MenuGtk::PopupAsFromKeyEvent(GtkWidget* widget) {
  Popup(widget, 0, gtk_get_current_event_time());
  gtk_menu_shell_select_first(GTK_MENU_SHELL(menu_.get()), FALSE);
}

void MenuGtk::Cancel() {
  gtk_menu_popdown(GTK_MENU(menu_.get()));
}

void MenuGtk::BuildMenuIn(GtkWidget* menu,
                          const MenuCreateMaterial* menu_data,
                          GtkAccelGroup* accel_group) {
  // We keep track of the last menu item in order to group radio items.
  GtkWidget* last_menu_item = NULL;
  for (; menu_data->type != MENU_END; ++menu_data) {
    GtkWidget* menu_item = NULL;

    std::string label;
    if (menu_data->label_argument) {
      label = l10n_util::GetStringFUTF8(
          menu_data->label_id,
          l10n_util::GetStringUTF16(menu_data->label_argument));
    } else if (menu_data->label_id) {
      label = l10n_util::GetStringUTF8(menu_data->label_id);
    } else if (menu_data->type != MENU_SEPARATOR) {
      label = delegate_->GetLabel(menu_data->id);
      DCHECK(!label.empty());
    }

    label = ConvertAcceleratorsFromWindowsStyle(label);

    switch (menu_data->type) {
      case MENU_RADIO:
        if (GTK_IS_RADIO_MENU_ITEM(last_menu_item)) {
          menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
              GTK_RADIO_MENU_ITEM(last_menu_item), label.c_str());
        } else {
          menu_item = gtk_radio_menu_item_new_with_mnemonic(
              NULL, label.c_str());
        }
        break;
      case MENU_CHECKBOX:
        menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
        break;
      case MENU_SEPARATOR:
        menu_item = gtk_separator_menu_item_new();
        break;
      case MENU_NORMAL:
      default:
        menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
        break;
    }

    if (menu_data->submenu) {
      GtkWidget* submenu = gtk_menu_new();
      BuildMenuIn(submenu, menu_data->submenu, accel_group);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
    } else if (menu_data->custom_submenu) {
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
                                menu_data->custom_submenu->menu_.get());
      submenus_we_own_.push_back(menu_data->custom_submenu);
    }

    if (menu_data->accel_key) {
      // If we ever want to let the user do any key remaping, we'll need to
      // change the following so we make a gtk_accel_map which keeps the actual
      // keys.
      gtk_widget_add_accelerator(menu_item,
                                 "activate",
                                 menu_data->only_show || !accel_group ?
                                     dummy_accel_group_ : accel_group,
                                 menu_data->accel_key,
                                 GdkModifierType(menu_data->accel_modifiers),
                                 GTK_ACCEL_VISIBLE);
    }

    g_object_set_data(G_OBJECT(menu_item), "menu-data",
                      const_cast<MenuCreateMaterial*>(menu_data));

    g_signal_connect(G_OBJECT(menu_item), "activate",
                     G_CALLBACK(OnMenuItemActivated), this);

    gtk_widget_show(menu_item);
    gtk_menu_append(menu, menu_item);
    last_menu_item = menu_item;
  }
}

GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
                                           const SkBitmap& icon) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_image_menu_item_new_with_mnemonic(converted_label.c_str());

  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
                                gtk_image_new_from_pixbuf(pixbuf));
  g_object_unref(pixbuf);
  if (delegate_->AlwaysShowImages())
    gtk_util::SetAlwaysShowImage(menu_item);

  return menu_item;
}

void MenuGtk::BuildMenuFromDelegate() {
  // Note that the menu IDs start at 1, not 0.
  for (int i = 1; i <= delegate_->GetItemCount(); ++i) {
    GtkWidget* menu_item = NULL;

    if (delegate_->IsItemSeparator(i)) {
      menu_item = gtk_separator_menu_item_new();
    } else if (delegate_->HasIcon(i)) {
      const SkBitmap* icon = delegate_->GetIcon(i);
      menu_item = BuildMenuItemWithImage(delegate_->GetLabel(i), *icon);
    } else {
      menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str());
    }

    AppendMenuItem(i, menu_item);
  }
}

// static
void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
  if (block_activation_)
    return;

  // We receive activation messages when highlighting a menu that has a
  // submenu. Ignore them.
  if (gtk_menu_item_get_submenu(menuitem))
    return;

  const MenuCreateMaterial* data =
      reinterpret_cast<const MenuCreateMaterial*>(
          g_object_get_data(G_OBJECT(menuitem), "menu-data"));

  int id;
  if (data) {
    id = data->id;
  } else {
    id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(menuitem),
                                                      "menu-id"));
  }

  // The menu item can still be activated by hotkeys even if it is disabled.
  if (menu->delegate_->IsCommandEnabled(id))
    menu->delegate_->ExecuteCommand(id);
}

// static
void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu,
                                     int* x,
                                     int* y,
                                     gboolean* push_in,
                                     void* void_widget) {
  GtkWidget* widget = GTK_WIDGET(void_widget);
  GtkRequisition menu_req;

  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);

  gdk_window_get_origin(widget->window, x, y);
  GdkScreen *screen = gtk_widget_get_screen(widget);
  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);

  GdkRectangle screen_rect;
  gdk_screen_get_monitor_geometry(screen, monitor,
                                  &screen_rect);

  if (GTK_WIDGET_NO_WINDOW(widget)) {
    *x += widget->allocation.x;
    *y += widget->allocation.y;
  }
  *y += widget->allocation.height;

  bool start_align =
    !!g_object_get_data(G_OBJECT(widget), "left-align-popup");
  if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
    start_align = !start_align;

  if (!start_align)
    *x += widget->allocation.width - menu_req.width;

  // If the menu would run off the bottom of the screen, and there is more
  // screen space up than down, then pop upwards.
  if (*y + menu_req.height >= screen_rect.height &&
      *y > screen_rect.height / 2) {
    *y -= menu_req.height;
  }

  *push_in = FALSE;
}

// static
void MenuGtk::PointMenuPositionFunc(GtkMenu* menu,
                                    int* x,
                                    int* y,
                                    gboolean* push_in,
                                    gpointer userdata) {
  *push_in = TRUE;

  gfx::Point* point = reinterpret_cast<gfx::Point*>(userdata);
  *x = point->x();
  *y = point->y();

  GtkRequisition menu_req;
  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
  GdkScreen* screen = gdk_screen_get_default();
  gint screen_height = gdk_screen_get_height(screen);

  if (*y + menu_req.height >= screen_height)
    *y -= menu_req.height;
}

void MenuGtk::UpdateMenu() {
  gtk_container_foreach(GTK_CONTAINER(menu_.get()), SetMenuItemInfo, this);
}

// static
void MenuGtk::OnMenuShow(GtkWidget* widget, MenuGtk* menu) {
  MessageLoop::current()->PostTask(FROM_HERE,
      menu->factory_.NewRunnableMethod(&MenuGtk::UpdateMenu));
}

// static
void MenuGtk::OnMenuHidden(GtkWidget* widget, MenuGtk* menu) {
  menu->delegate_->StoppedShowing();
}

// static
void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
  if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) {
    // We need to explicitly handle this case because otherwise we'll ask the
    // menu delegate about something with an invalid id.
    return;
  }

  MenuGtk* menu = reinterpret_cast<MenuGtk*>(userdata);
  int id;
  const MenuCreateMaterial* data =
      reinterpret_cast<const MenuCreateMaterial*>(
          g_object_get_data(G_OBJECT(widget), "menu-data"));
  if (data) {
    id = data->id;
  } else {
    id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
                                    "menu-id"));
  }

  if (GTK_IS_CHECK_MENU_ITEM(widget)) {
    GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);

    // gtk_check_menu_item_set_active() will send the activate signal. Touching
    // the underlying "active" property will also call the "activate" handler
    // for this menu item. So we prevent the "activate" handler from
    // being called while we set the checkbox.
    // Why not use one of the glib signal-blocking functions?  Because when we
    // toggle a radio button, it will deactivate one of the other radio buttons,
    // which we don't have a pointer to.
    // Wny not make this a member variable?  Because "menu" is a pointer to the
    // root of the MenuGtk and we want to disable *all* MenuGtks, including
    // submenus.
    block_activation_ = true;
    gtk_check_menu_item_set_active(item, menu->delegate_->IsItemChecked(id));
    block_activation_ = false;
  }

  if (GTK_IS_MENU_ITEM(widget)) {
    gtk_widget_set_sensitive(
        widget, menu->delegate_->IsCommandEnabled(id));

    GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
    if (submenu) {
      gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
                            userdata);
    }
  }
}
<commit_msg>Fix radio items in MenuGtk.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/menu_gtk.h"

#include "app/gfx/gtk_util.h"
#include "app/l10n_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "chrome/browser/gtk/standard_menus.h"
#include "chrome/common/gtk_util.h"
#include "third_party/skia/include/core/SkBitmap.h"

using gtk_util::ConvertAcceleratorsFromWindowsStyle;

bool MenuGtk::block_activation_ = false;

MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
                 const MenuCreateMaterial* menu_data,
                 GtkAccelGroup* accel_group)
    : delegate_(delegate),
      dummy_accel_group_(gtk_accel_group_new()),
      menu_(gtk_menu_new()),
      factory_(this) {
  ConnectSignalHandlers();
  BuildMenuIn(menu_.get(), menu_data, accel_group);
}

MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, bool load)
    : delegate_(delegate),
      dummy_accel_group_(NULL),
      menu_(gtk_menu_new()),
      factory_(this) {
  ConnectSignalHandlers();
  if (load)
    BuildMenuFromDelegate();
}

MenuGtk::~MenuGtk() {
  menu_.Destroy();
  STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
  if (dummy_accel_group_)
    g_object_unref(dummy_accel_group_);
}

void MenuGtk::ConnectSignalHandlers() {
  // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
  // take a long time or even start a nested message loop.
  g_signal_connect(menu_.get(), "show", G_CALLBACK(OnMenuShow), this);
  g_signal_connect(menu_.get(), "hide", G_CALLBACK(OnMenuHidden), this);
}

void MenuGtk::AppendMenuItemWithLabel(int command_id,
                                      const std::string& label) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_menu_item_new_with_mnemonic(converted_label.c_str());
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendMenuItemWithIcon(int command_id,
                                     const std::string& label,
                                     const SkBitmap& icon) {
  GtkWidget* menu_item = BuildMenuItemWithImage(label, icon);
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendCheckMenuItemWithLabel(int command_id,
                                           const std::string& label) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_check_menu_item_new_with_mnemonic(converted_label.c_str());
  AppendMenuItem(command_id, menu_item);
}

void MenuGtk::AppendSeparator() {
  GtkWidget* menu_item = gtk_separator_menu_item_new();
  gtk_widget_show(menu_item);
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_.get()), menu_item);
}

void MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
  g_object_set_data(G_OBJECT(menu_item), "menu-id",
                    reinterpret_cast<void*>(command_id));

  g_signal_connect(G_OBJECT(menu_item), "activate",
                   G_CALLBACK(OnMenuItemActivated), this);

  gtk_widget_show(menu_item);
  gtk_menu_shell_append(GTK_MENU_SHELL(menu_.get()), menu_item);
}

void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
  DCHECK(event->type == GDK_BUTTON_PRESS)
      << "Non-button press event sent to RunMenuAt";

  GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
  Popup(widget, event_button->button, event_button->time);
}

void MenuGtk::Popup(GtkWidget* widget, gint button_type, guint32 timestamp) {
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL,
                 WidgetMenuPositionFunc,
                 widget,
                 button_type, timestamp);
}

void MenuGtk::PopupAsContext(guint32 event_time) {
  // TODO(estade): |button| value of 3 (6th argument) is not strictly true,
  // but does it matter?
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL, NULL, NULL, 3, event_time);
}

void MenuGtk::PopupAsContextAt(guint32 event_time, gfx::Point point) {
  gtk_menu_popup(GTK_MENU(menu_.get()), NULL, NULL,
                 PointMenuPositionFunc, &point, 3, event_time);
}

void MenuGtk::PopupAsFromKeyEvent(GtkWidget* widget) {
  Popup(widget, 0, gtk_get_current_event_time());
  gtk_menu_shell_select_first(GTK_MENU_SHELL(menu_.get()), FALSE);
}

void MenuGtk::Cancel() {
  gtk_menu_popdown(GTK_MENU(menu_.get()));
}

void MenuGtk::BuildMenuIn(GtkWidget* menu,
                          const MenuCreateMaterial* menu_data,
                          GtkAccelGroup* accel_group) {
  // We keep track of the last menu item in order to group radio items.
  GtkWidget* last_menu_item = NULL;
  for (; menu_data->type != MENU_END; ++menu_data) {
    GtkWidget* menu_item = NULL;

    std::string label;
    if (menu_data->label_argument) {
      label = l10n_util::GetStringFUTF8(
          menu_data->label_id,
          l10n_util::GetStringUTF16(menu_data->label_argument));
    } else if (menu_data->label_id) {
      label = l10n_util::GetStringUTF8(menu_data->label_id);
    } else if (menu_data->type != MENU_SEPARATOR) {
      label = delegate_->GetLabel(menu_data->id);
      DCHECK(!label.empty());
    }

    label = ConvertAcceleratorsFromWindowsStyle(label);

    switch (menu_data->type) {
      case MENU_RADIO:
        if (GTK_IS_RADIO_MENU_ITEM(last_menu_item)) {
          menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
              GTK_RADIO_MENU_ITEM(last_menu_item), label.c_str());
        } else {
          menu_item = gtk_radio_menu_item_new_with_mnemonic(
              NULL, label.c_str());
        }
        break;
      case MENU_CHECKBOX:
        menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
        break;
      case MENU_SEPARATOR:
        menu_item = gtk_separator_menu_item_new();
        break;
      case MENU_NORMAL:
      default:
        menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
        break;
    }

    if (menu_data->submenu) {
      GtkWidget* submenu = gtk_menu_new();
      BuildMenuIn(submenu, menu_data->submenu, accel_group);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
    } else if (menu_data->custom_submenu) {
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
                                menu_data->custom_submenu->menu_.get());
      submenus_we_own_.push_back(menu_data->custom_submenu);
    }

    if (menu_data->accel_key) {
      // If we ever want to let the user do any key remaping, we'll need to
      // change the following so we make a gtk_accel_map which keeps the actual
      // keys.
      gtk_widget_add_accelerator(menu_item,
                                 "activate",
                                 menu_data->only_show || !accel_group ?
                                     dummy_accel_group_ : accel_group,
                                 menu_data->accel_key,
                                 GdkModifierType(menu_data->accel_modifiers),
                                 GTK_ACCEL_VISIBLE);
    }

    g_object_set_data(G_OBJECT(menu_item), "menu-data",
                      const_cast<MenuCreateMaterial*>(menu_data));

    g_signal_connect(G_OBJECT(menu_item), "activate",
                     G_CALLBACK(OnMenuItemActivated), this);

    gtk_widget_show(menu_item);
    gtk_menu_append(menu, menu_item);
    last_menu_item = menu_item;
  }
}

GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
                                           const SkBitmap& icon) {
  std::string converted_label = ConvertAcceleratorsFromWindowsStyle(label);
  GtkWidget* menu_item =
      gtk_image_menu_item_new_with_mnemonic(converted_label.c_str());

  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
                                gtk_image_new_from_pixbuf(pixbuf));
  g_object_unref(pixbuf);
  if (delegate_->AlwaysShowImages())
    gtk_util::SetAlwaysShowImage(menu_item);

  return menu_item;
}

void MenuGtk::BuildMenuFromDelegate() {
  // Note that the menu IDs start at 1, not 0.
  for (int i = 1; i <= delegate_->GetItemCount(); ++i) {
    GtkWidget* menu_item = NULL;

    if (delegate_->IsItemSeparator(i)) {
      menu_item = gtk_separator_menu_item_new();
    } else if (delegate_->HasIcon(i)) {
      const SkBitmap* icon = delegate_->GetIcon(i);
      menu_item = BuildMenuItemWithImage(delegate_->GetLabel(i), *icon);
    } else {
      menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str());
    }

    AppendMenuItem(i, menu_item);
  }
}

// static
void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
  if (block_activation_)
    return;

  // We receive activation messages when highlighting a menu that has a
  // submenu. Ignore them.
  if (gtk_menu_item_get_submenu(menuitem))
    return;

  // The activate signal is sent to radio items as they get deselected;
  // ignore it in this case.
  if (GTK_IS_RADIO_MENU_ITEM(menuitem) &&
      !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
    return;
  }

  const MenuCreateMaterial* data =
      reinterpret_cast<const MenuCreateMaterial*>(
          g_object_get_data(G_OBJECT(menuitem), "menu-data"));

  int id;
  if (data) {
    id = data->id;
  } else {
    id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(menuitem),
                                                      "menu-id"));
  }

  // The menu item can still be activated by hotkeys even if it is disabled.
  if (menu->delegate_->IsCommandEnabled(id))
    menu->delegate_->ExecuteCommand(id);
}

// static
void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu,
                                     int* x,
                                     int* y,
                                     gboolean* push_in,
                                     void* void_widget) {
  GtkWidget* widget = GTK_WIDGET(void_widget);
  GtkRequisition menu_req;

  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);

  gdk_window_get_origin(widget->window, x, y);
  GdkScreen *screen = gtk_widget_get_screen(widget);
  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);

  GdkRectangle screen_rect;
  gdk_screen_get_monitor_geometry(screen, monitor,
                                  &screen_rect);

  if (GTK_WIDGET_NO_WINDOW(widget)) {
    *x += widget->allocation.x;
    *y += widget->allocation.y;
  }
  *y += widget->allocation.height;

  bool start_align =
    !!g_object_get_data(G_OBJECT(widget), "left-align-popup");
  if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
    start_align = !start_align;

  if (!start_align)
    *x += widget->allocation.width - menu_req.width;

  // If the menu would run off the bottom of the screen, and there is more
  // screen space up than down, then pop upwards.
  if (*y + menu_req.height >= screen_rect.height &&
      *y > screen_rect.height / 2) {
    *y -= menu_req.height;
  }

  *push_in = FALSE;
}

// static
void MenuGtk::PointMenuPositionFunc(GtkMenu* menu,
                                    int* x,
                                    int* y,
                                    gboolean* push_in,
                                    gpointer userdata) {
  *push_in = TRUE;

  gfx::Point* point = reinterpret_cast<gfx::Point*>(userdata);
  *x = point->x();
  *y = point->y();

  GtkRequisition menu_req;
  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
  GdkScreen* screen = gdk_screen_get_default();
  gint screen_height = gdk_screen_get_height(screen);

  if (*y + menu_req.height >= screen_height)
    *y -= menu_req.height;
}

void MenuGtk::UpdateMenu() {
  gtk_container_foreach(GTK_CONTAINER(menu_.get()), SetMenuItemInfo, this);
}

// static
void MenuGtk::OnMenuShow(GtkWidget* widget, MenuGtk* menu) {
  MessageLoop::current()->PostTask(FROM_HERE,
      menu->factory_.NewRunnableMethod(&MenuGtk::UpdateMenu));
}

// static
void MenuGtk::OnMenuHidden(GtkWidget* widget, MenuGtk* menu) {
  menu->delegate_->StoppedShowing();
}

// static
void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
  if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) {
    // We need to explicitly handle this case because otherwise we'll ask the
    // menu delegate about something with an invalid id.
    return;
  }

  MenuGtk* menu = reinterpret_cast<MenuGtk*>(userdata);
  int id;
  const MenuCreateMaterial* data =
      reinterpret_cast<const MenuCreateMaterial*>(
          g_object_get_data(G_OBJECT(widget), "menu-data"));
  if (data) {
    id = data->id;
  } else {
    id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
                                    "menu-id"));
  }

  if (GTK_IS_CHECK_MENU_ITEM(widget)) {
    GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);

    // gtk_check_menu_item_set_active() will send the activate signal. Touching
    // the underlying "active" property will also call the "activate" handler
    // for this menu item. So we prevent the "activate" handler from
    // being called while we set the checkbox.
    // Why not use one of the glib signal-blocking functions?  Because when we
    // toggle a radio button, it will deactivate one of the other radio buttons,
    // which we don't have a pointer to.
    // Wny not make this a member variable?  Because "menu" is a pointer to the
    // root of the MenuGtk and we want to disable *all* MenuGtks, including
    // submenus.
    block_activation_ = true;
    gtk_check_menu_item_set_active(item, menu->delegate_->IsItemChecked(id));
    block_activation_ = false;
  }

  if (GTK_IS_MENU_ITEM(widget)) {
    gtk_widget_set_sensitive(
        widget, menu->delegate_->IsCommandEnabled(id));

    GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
    if (submenu) {
      gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
                            userdata);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));

#if defined(OS_WIN)
    std::wstring pepper_plugin = plugin_lib.value();
#else
    std::wstring pepper_plugin = UTF8ToWide(plugin_lib.value());
#endif
    pepper_plugin.append(L";application/x-ppapi-tests");
    launch_arguments_.AppendSwitchWithValue(switches::kRegisterPepperPlugins,
                                            pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);
  }

  void RunTest(const FilePath::StringType& test_file_name) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(test_file_name);

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL test_url = net::FilePathToFileURL(test_path);
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

#if defined(OS_WIN)
TEST_F(PPAPITest, DeviceContext2D) {
#else
// TODO(brettw) currently fails on Mac & Linux 64 for unknown reasons.
TEST_F(PPAPITest, DISABLED_DeviceContext2D) {
#endif
  RunTest(FILE_PATH_LITERAL("test_device_context_2d.html"));
}

TEST_F(PPAPITest, ImageData) {
  RunTest(FILE_PATH_LITERAL("test_image_data.html"));
}
<commit_msg>Disable the ImageData test on Mac which is failing.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));

#if defined(OS_WIN)
    std::wstring pepper_plugin = plugin_lib.value();
#else
    std::wstring pepper_plugin = UTF8ToWide(plugin_lib.value());
#endif
    pepper_plugin.append(L";application/x-ppapi-tests");
    launch_arguments_.AppendSwitchWithValue(switches::kRegisterPepperPlugins,
                                            pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);
  }

  void RunTest(const FilePath::StringType& test_file_name) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(test_file_name);

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL test_url = net::FilePathToFileURL(test_path);
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

#if defined(OS_WIN)
TEST_F(PPAPITest, DeviceContext2D) {
#else
// TODO(brettw) currently fails on Mac & Linux 64 for unknown reasons.
TEST_F(PPAPITest, DISABLED_DeviceContext2D) {
#endif
  RunTest(FILE_PATH_LITERAL("test_device_context_2d.html"));
}

#if defined(OS_MACOSX)
// TODO(brettw) this fails on Mac for unknown reasons.
TEST_F(PPAPITest, DISABLED_ImageData) {
#else
TEST_F(PPAPITest, ImageData) {
#endif
  RunTest(FILE_PATH_LITERAL("test_image_data.html"));
}
<|endoftext|>


<commit_before>#ifndef CONFIGMGR_LOCALBE_LOCALFILEHELPER_HXX_
#include "localfilehelper.hxx"
#endif

#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <vector>

namespace configmgr
{
 namespace localbe
 {
    //------------------------------------------------------------------------------
    bool isValidFileURL (rtl::OUString const& _sFileURL)
    {
        using osl::File;

        rtl::OUString sSystemPath;
        return _sFileURL.getLength() && (File::E_None == File::getSystemPathFromFileURL(_sFileURL, sSystemPath));
    }
    //------------------------------------------------------------------------------
    void validateFileURL(const rtl::OUString& _sFileURL, const uno::Reference<uno::XInterface>& pContext)
        throw(css::configuration::InvalidBootstrapFileException)
    {
        if (!isValidFileURL( _sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" Not a Valid File URL: \"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\"");
            throw com::sun::star::configuration::InvalidBootstrapFileException(
                sMsg.makeStringAndClear(),pContext, rtl::OUString() ) ;
        }
    }
    //------------------------------------------------------------------------------
    void checkFileExists(const rtl::OUString& _sFileURL,const uno::Reference<uno::XInterface>& pContext)
        throw (backend::CannotConnectException)
    {
        if (!FileHelper::fileExists(_sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" No Such File or Directory: \"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\"");

            throw backend::CannotConnectException(sMsg.makeStringAndClear(), pContext, uno::Any()) ;
        }
    }
    //------------------------------------------------------------------------------
    void checkIfDirectory(const rtl::OUString& _sFileURL, const uno::Reference<uno::XInterface>& pContext)
        throw (backend::BackendSetupException)
    {
        if (!FileHelper::dirExists(_sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" File:\"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\" Must be a Directory\"");

            throw backend::BackendSetupException(sMsg.makeStringAndClear(),pContext, uno::Any()) ;
        }
    }

    // ---------------------------------------------------------------------------------------
    bool implEnsureAbsoluteURL(rtl::OUString & _rsURL) // also strips embedded dots etc.
    {
        using osl::File;

        rtl::OUString sBasePath = _rsURL;
        OSL_VERIFY(osl_Process_E_None == osl_getProcessWorkingDir(&sBasePath.pData));

        rtl::OUString sAbsolute;
        if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute))
        {
            _rsURL = sAbsolute;
            return true;
        }
        else
        {
            OSL_ENSURE(false, "Could not get absolute file URL for valid URL");
            return false;
        }
    }
    // ---------------------------------------------------------------------------------------
    osl::DirectoryItem::RC implNormalizeURL(rtl::OUString & _sURL, osl::DirectoryItem& aDirItem)
    {
        using namespace osl;

        OSL_PRECOND(aDirItem.is(), "Opened DirItem required");

        static const sal_uInt32 cFileStatusMask = FileStatusMask_FileURL;

        FileStatus aFileStatus(cFileStatusMask);

        DirectoryItem::RC rc = aDirItem.getFileStatus(aFileStatus);

        if (rc == DirectoryItem::E_None)
        {
            rtl::OUString aNormalizedURL = aFileStatus.getFileURL();

            if (aNormalizedURL.getLength() != 0)
                _sURL = aNormalizedURL;
            else
                rc = DirectoryItem::E_INVAL;
        }
        return rc;
    }

    // ---------------------------------------------------------------------------------------

    bool normalizeURL(rtl::OUString & _sURL,  const uno::Reference<uno::XInterface>& pContext, bool bNothrow )
      throw (backend::InsufficientAccessRightsException, backend::BackendAccessException)
    {

        using namespace osl;

        if (_sURL.getLength() == 0)
            return false;

        DirectoryItem aDirItem;

        DirectoryItem::RC rc = DirectoryItem::get(_sURL, aDirItem);

        if (rc == DirectoryItem::E_None)
            rc = implNormalizeURL(_sURL,aDirItem);

        switch (rc)
        {
        case DirectoryItem::E_None:  return true;

        case DirectoryItem::E_NOENT: return true;

        case DirectoryItem::E_ACCES:
           if (!bNothrow)
           {
               rtl::OUStringBuffer msg;
               msg.appendAscii("LocalBackend: Cannot normalize URL \"" );
               msg.append(_sURL);
               msg.appendAscii("\" - InsufficientAccess");
               throw backend::InsufficientAccessRightsException(msg.makeStringAndClear(),pContext,uno::Any());
           }
           return false;

        default:
            if (!bNothrow)
            {
                rtl::OUStringBuffer msg;
                msg.appendAscii("LocalBackend: Cannot normalize URL \"" );
                msg.append(_sURL);
                msg.appendAscii("\" - ").append(FileHelper::createOSLErrorString(rc));
                throw backend::BackendAccessException(msg.makeStringAndClear(),pContext,uno::Any());
            }
            return false;

        }
    }

    // ---------------------------------------------------------------------------------------
    static sal_Unicode kComponentSeparator = '.' ;
    static sal_Unicode kPathSeparator = '/' ;

    rtl::OUString componentToPath(const rtl::OUString& aComponent)
    {
        rtl::OUStringBuffer retCode ;

        retCode.append(kPathSeparator) ;
        retCode.append(aComponent.replace(kComponentSeparator, kPathSeparator)) ;
        return retCode.makeStringAndClear() ;
    }
    //------------------------------------------------------------------------------
    bool checkOptionalArg(rtl::OUString& aArg)
    {
        if (aArg.getLength() && aArg[0] == sal_Unicode('?'))
        {
            aArg = aArg.copy(1);
            return true;
        }
        else
        {
            return false;
        }
    }
    //------------------------------------------------------------------------------
    void fillFromBlankSeparated(const rtl::OUString& aList,
                                uno::Sequence<rtl::OUString>& aTarget)
    {
        std::vector<rtl::OUString> tokens ;
        sal_Int32 nextToken = 0 ;

        do {
            tokens.push_back(aList.getToken(0, ' ', nextToken)) ;
        } while (nextToken >= 0) ;
        if (tokens.size() > 0) {
            aTarget.realloc(tokens.size()) ;
            std::vector<rtl::OUString>::const_iterator token ;
            sal_Int32 i = 0 ;

            for (token = tokens.begin() ; token != tokens.end() ; ++ token) {
                aTarget [i ++] = *token ;
            }
        }
    }
    //------------------------------------------------------------------------------
  }
} // namespace configmgr
<commit_msg>INTEGRATION: CWS adabas13 (1.2.58); FILE MERGED 2005/01/25 13:13:29 jb 1.2.58.1: #119211# Improve entity handling to support multi-stratum sublayers which have dots in their names<commit_after>#ifndef CONFIGMGR_LOCALBE_LOCALFILEHELPER_HXX_
#include "localfilehelper.hxx"
#endif

#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <vector>

namespace configmgr
{
 namespace localbe
 {
    //------------------------------------------------------------------------------
    bool isValidFileURL (rtl::OUString const& _sFileURL)
    {
        using osl::File;

        rtl::OUString sSystemPath;
        return _sFileURL.getLength() && (File::E_None == File::getSystemPathFromFileURL(_sFileURL, sSystemPath));
    }
    //------------------------------------------------------------------------------
    void validateFileURL(const rtl::OUString& _sFileURL, const uno::Reference<uno::XInterface>& pContext)
        throw(css::configuration::InvalidBootstrapFileException)
    {
        if (!isValidFileURL( _sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" Not a Valid File URL: \"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\"");
            throw com::sun::star::configuration::InvalidBootstrapFileException(
                sMsg.makeStringAndClear(),pContext, rtl::OUString() ) ;
        }
    }
    //------------------------------------------------------------------------------
    void checkFileExists(const rtl::OUString& _sFileURL,const uno::Reference<uno::XInterface>& pContext)
        throw (backend::CannotConnectException)
    {
        if (!FileHelper::fileExists(_sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" No Such File or Directory: \"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\"");

            throw backend::CannotConnectException(sMsg.makeStringAndClear(), pContext, uno::Any()) ;
        }
    }
    //------------------------------------------------------------------------------
    void checkIfDirectory(const rtl::OUString& _sFileURL, const uno::Reference<uno::XInterface>& pContext)
        throw (backend::BackendSetupException)
    {
        if (!FileHelper::dirExists(_sFileURL))
        {
            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii(" File:\"");
            sMsg.append(_sFileURL);
            sMsg.appendAscii("\" Must be a Directory\"");

            throw backend::BackendSetupException(sMsg.makeStringAndClear(),pContext, uno::Any()) ;
        }
    }

    // ---------------------------------------------------------------------------------------
    bool implEnsureAbsoluteURL(rtl::OUString & _rsURL) // also strips embedded dots etc.
    {
        using osl::File;

        rtl::OUString sBasePath = _rsURL;
        OSL_VERIFY(osl_Process_E_None == osl_getProcessWorkingDir(&sBasePath.pData));

        rtl::OUString sAbsolute;
        if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute))
        {
            _rsURL = sAbsolute;
            return true;
        }
        else
        {
            OSL_ENSURE(false, "Could not get absolute file URL for valid URL");
            return false;
        }
    }
    // ---------------------------------------------------------------------------------------
    osl::DirectoryItem::RC implNormalizeURL(rtl::OUString & _sURL, osl::DirectoryItem& aDirItem)
    {
        using namespace osl;

        OSL_PRECOND(aDirItem.is(), "Opened DirItem required");

        static const sal_uInt32 cFileStatusMask = FileStatusMask_FileURL;

        FileStatus aFileStatus(cFileStatusMask);

        DirectoryItem::RC rc = aDirItem.getFileStatus(aFileStatus);

        if (rc == DirectoryItem::E_None)
        {
            rtl::OUString aNormalizedURL = aFileStatus.getFileURL();

            if (aNormalizedURL.getLength() != 0)
                _sURL = aNormalizedURL;
            else
                rc = DirectoryItem::E_INVAL;
        }
        return rc;
    }

    // ---------------------------------------------------------------------------------------

    bool normalizeURL(rtl::OUString & _sURL,  const uno::Reference<uno::XInterface>& pContext, bool bNothrow )
      throw (backend::InsufficientAccessRightsException, backend::BackendAccessException)
    {

        using namespace osl;

        if (_sURL.getLength() == 0)
            return false;

        DirectoryItem aDirItem;

        DirectoryItem::RC rc = DirectoryItem::get(_sURL, aDirItem);

        if (rc == DirectoryItem::E_None)
            rc = implNormalizeURL(_sURL,aDirItem);

        switch (rc)
        {
        case DirectoryItem::E_None:  return true;

        case DirectoryItem::E_NOENT: return true;

        case DirectoryItem::E_ACCES:
           if (!bNothrow)
           {
               rtl::OUStringBuffer msg;
               msg.appendAscii("LocalBackend: Cannot normalize URL \"" );
               msg.append(_sURL);
               msg.appendAscii("\" - InsufficientAccess");
               throw backend::InsufficientAccessRightsException(msg.makeStringAndClear(),pContext,uno::Any());
           }
           return false;

        default:
            if (!bNothrow)
            {
                rtl::OUStringBuffer msg;
                msg.appendAscii("LocalBackend: Cannot normalize URL \"" );
                msg.append(_sURL);
                msg.appendAscii("\" - ").append(FileHelper::createOSLErrorString(rc));
                throw backend::BackendAccessException(msg.makeStringAndClear(),pContext,uno::Any());
            }
            return false;

        }
    }

    // ---------------------------------------------------------------------------------------
    static const sal_Unicode kComponentSeparator = '.' ;
    static const sal_Unicode kPathSeparator = '/' ;

    rtl::OUString componentToPath(const rtl::OUString& aComponent)
    {
        rtl::OUStringBuffer retCode ;

        retCode.append(kPathSeparator) ;
        retCode.append(aComponent.replace(kComponentSeparator, kPathSeparator)) ;
        return retCode.makeStringAndClear() ;
    }
    //------------------------------------------------------------------------------
    rtl::OUString layeridToPath(const rtl::OUString& aLayerId)
    {
        sal_Int32 const nSplit = aLayerId.indexOf(k_cLayerIdSeparator);
        if (nSplit < 0)
            return componentToPath(aLayerId);

        rtl::OUString const aComponent= aLayerId.copy(0,nSplit);
        rtl::OUString const aSubid = aLayerId.copy(nSplit+1);

        rtl::OUStringBuffer retCode ;

        retCode.append(kPathSeparator) ;
        retCode.append(aComponent.replace(kComponentSeparator, kPathSeparator)) ;
        retCode.append(kPathSeparator) ;
        retCode.append(aSubid) ;
        return retCode.makeStringAndClear() ;
    }
    //------------------------------------------------------------------------------
    bool checkOptionalArg(rtl::OUString& aArg)
    {
        if (aArg.getLength() && aArg[0] == sal_Unicode('?'))
        {
            aArg = aArg.copy(1);
            return true;
        }
        else
        {
            return false;
        }
    }
    //------------------------------------------------------------------------------
    void fillFromBlankSeparated(const rtl::OUString& aList,
                                uno::Sequence<rtl::OUString>& aTarget)
    {
        std::vector<rtl::OUString> tokens ;
        sal_Int32 nextToken = 0 ;

        do {
            tokens.push_back(aList.getToken(0, ' ', nextToken)) ;
        } while (nextToken >= 0) ;
        if (tokens.size() > 0) {
            aTarget.realloc(tokens.size()) ;
            std::vector<rtl::OUString>::const_iterator token ;
            sal_Int32 i = 0 ;

            for (token = tokens.begin() ; token != tokens.end() ; ++ token) {
                aTarget [i ++] = *token ;
            }
        }
    }
    //------------------------------------------------------------------------------
  }
} // namespace configmgr
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "camerabinvideoencoder.h"
#include "camerabinsession.h"
#include "camerabincontainer.h"

#include <QtCore/qdebug.h>

CameraBinVideoEncoder::CameraBinVideoEncoder(CameraBinSession *session)
    :QVideoEncoderControl(session), m_session(session)
{
    QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    codecCandidates << "video/mpeg4" << "video/h264" << "video/h263" << "video/theora"
                    << "video/mpeg2" << "video/mpeg1" << "video/mjpeg" << "video/VP8" << "video/h261";

    m_elementNames["video/h264"] = "dsph264enc";
    m_elementNames["video/mpeg4"] = "dspmp4venc";
    m_elementNames["video/h263"] = "dsph263enc";
    m_elementNames["video/theora"] = "theoraenc";
    m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
    m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
    m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
    m_elementNames["video/VP8"] = "vp8enc";
    m_elementNames["video/h261"] = "ffenc_h261";

    m_codecOptions["video/mpeg4"] = QStringList() << "mode" << "keyframe-interval";
#else
    codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4"
                    << "video/mpeg1" << "video/mpeg2" << "video/theora"
                    << "video/VP8" << "video/h261" << "video/mjpeg";

    m_elementNames["video/h264"] = "x264enc";
    m_elementNames["video/xvid"] = "xvidenc";
    m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
    m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
    m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
    m_elementNames["video/theora"] = "theoraenc";
    m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
    m_elementNames["video/VP8"] = "vp8enc";
    m_elementNames["video/h261"] = "ffenc_h261";

    m_codecOptions["video/h264"] = QStringList() << "quantizer";
    m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
    m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
    m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
    m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
    m_codecOptions["video/theora"] = QStringList();

#endif

    foreach( const QByteArray& codecName, codecCandidates ) {
        QByteArray elementName = m_elementNames[codecName];
        GstElementFactory *factory = gst_element_factory_find(elementName.constData());
        if (factory) {
            m_codecs.append(codecName);
            const gchar *descr = gst_element_factory_get_description(factory);
            m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));

            m_streamTypes.insert(codecName,
                                 CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));

            gst_object_unref(GST_OBJECT(factory));
        }
    }
}

CameraBinVideoEncoder::~CameraBinVideoEncoder()
{
}

QList<QSize> CameraBinVideoEncoder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
{
    if (continuous)
        *continuous = false;

    QPair<int,int> rate = rateAsRational(settings.frameRate());

    //select the closest supported rational rate to settings.frameRate()

    return m_session->supportedResolutions(rate, continuous);
}

QList< qreal > CameraBinVideoEncoder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
{
    if (continuous)
        *continuous = false;

    QList< qreal > res;
    QPair<int,int> rate;

    foreach(rate, m_session->supportedFrameRates(settings.resolution(), continuous)) {
        if (rate.second > 0)
            res << qreal(rate.first)/rate.second;
    }

    return res;
}

QStringList CameraBinVideoEncoder::supportedVideoCodecs() const
{
    return m_codecs;
}

QString CameraBinVideoEncoder::videoCodecDescription(const QString &codecName) const
{
    return m_codecDescriptions.value(codecName);
}

QStringList CameraBinVideoEncoder::supportedEncodingOptions(const QString &codec) const
{
    return m_codecOptions.value(codec);
}

QVariant CameraBinVideoEncoder::encodingOption(const QString &codec, const QString &name) const
{
    return m_options[codec].value(name);
}

void CameraBinVideoEncoder::setEncodingOption(
        const QString &codec, const QString &name, const QVariant &value)
{
    m_options[codec][name] = value;
}

QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const
{
    return m_videoSettings;
}

void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
{
    m_videoSettings = settings;
    m_userSettings = settings;
    emit settingsChanged();
}

void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
{
    m_videoSettings = settings;
}

void CameraBinVideoEncoder::resetActualSettings()
{
    m_videoSettings = m_userSettings;
}

GstElement *CameraBinVideoEncoder::createEncoder()
{
    QString codec = m_videoSettings.codec();
    QByteArray elementName = m_elementNames.value(codec);

    GstElement *encoderElement = gst_element_factory_make( elementName.constData(), "video-encoder");

    if (encoderElement) {
        if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
            QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();

            if (elementName == "x264enc") {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
                int qualityTable[] = {
                    50, //VeryLow
                    35, //Low
                    21, //Normal
                    15, //High
                    8 //VeryHigh
                };
                g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
            } else if (elementName == "xvidenc") {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
                int qualityTable[] = {
                    32, //VeryLow
                    12, //Low
                    5, //Normal
                    3, //High
                    2 //VeryHigh
                };
                int quant = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
            } else if (elementName == "ffenc_mpeg4" ||
                       elementName == "ffenc_mpeg1video" ||
                       elementName == "ffenc_mpeg2video" ) {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
                //quant from 1 to 30, default ~3
                double qualityTable[] = {
                    20, //VeryLow
                    8.0, //Low
                    3.0, //Normal
                    2.5, //High
                    2.0 //VeryHigh
                };
                double quant = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
            } else if (elementName == "theoraenc") {
                int qualityTable[] = {
                    8, //VeryLow
                    16, //Low
                    32, //Normal
                    45, //High
                    60 //VeryHigh
                };
                //quality from 0 to 63
                int quality = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
            } else if (elementName == "dsph264enc" ||
                       elementName == "dspmp4venc" ||
                       elementName == "dsph263enc") {
                //only bitrate parameter is supported
                int qualityTable[] = {
                    1000000, //VeryLow
                    2000000, //Low
                    4000000, //Normal
                    8000000, //High
                    16000000 //VeryHigh
                };
                //quality from 0 to 63
                int bitrate = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
            }
        } else {
            int bitrate = m_videoSettings.bitRate();
            if (bitrate > 0) {
                g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
            }
        }

        QMap<QString,QVariant> options = m_options.value(codec);
        QMapIterator<QString,QVariant> it(options);
        while (it.hasNext()) {
            it.next();
            QString option = it.key();
            QVariant value = it.value();

            switch (value.type()) {
            case QVariant::Int:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
                break;
            case QVariant::Bool:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
                break;
            case QVariant::Double:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
                break;
            case QVariant::String:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
                break;
            default:
                qWarning() << "unsupported option type:" << option << value;
                break;
            }

        }
    }

    return encoderElement;
}

QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
{
    if (frameRate > 0.001) {
        //convert to rational number
        QList<int> denumCandidates;
        denumCandidates << 1 << 2 << 3 << 5 << 10 << 25 << 30 << 50 << 100 << 1001 << 1000;

        qreal error = 1.0;
        int num = 1;
        int denum = 1;

        foreach (int curDenum, denumCandidates) {
            int curNum = qRound(frameRate*curDenum);
            qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);

            if (curError < error) {
                error = curError;
                num = curNum;
                denum = curDenum;
            }

            if (curError < 1e-8)
                break;
        }

        return QPair<int,int>(num,denum);
    }

    return QPair<int,int>();
}

QSet<QString> CameraBinVideoEncoder::supportedStreamTypes(const QString &codecName) const
{
    return m_streamTypes.value(codecName);
}
<commit_msg>Camerabin backend: removed invalid comment.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "camerabinvideoencoder.h"
#include "camerabinsession.h"
#include "camerabincontainer.h"

#include <QtCore/qdebug.h>

CameraBinVideoEncoder::CameraBinVideoEncoder(CameraBinSession *session)
    :QVideoEncoderControl(session), m_session(session)
{
    QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    codecCandidates << "video/mpeg4" << "video/h264" << "video/h263" << "video/theora"
                    << "video/mpeg2" << "video/mpeg1" << "video/mjpeg" << "video/VP8" << "video/h261";

    m_elementNames["video/h264"] = "dsph264enc";
    m_elementNames["video/mpeg4"] = "dspmp4venc";
    m_elementNames["video/h263"] = "dsph263enc";
    m_elementNames["video/theora"] = "theoraenc";
    m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
    m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
    m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
    m_elementNames["video/VP8"] = "vp8enc";
    m_elementNames["video/h261"] = "ffenc_h261";

    m_codecOptions["video/mpeg4"] = QStringList() << "mode" << "keyframe-interval";
#else
    codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4"
                    << "video/mpeg1" << "video/mpeg2" << "video/theora"
                    << "video/VP8" << "video/h261" << "video/mjpeg";

    m_elementNames["video/h264"] = "x264enc";
    m_elementNames["video/xvid"] = "xvidenc";
    m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
    m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
    m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
    m_elementNames["video/theora"] = "theoraenc";
    m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
    m_elementNames["video/VP8"] = "vp8enc";
    m_elementNames["video/h261"] = "ffenc_h261";

    m_codecOptions["video/h264"] = QStringList() << "quantizer";
    m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
    m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
    m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
    m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
    m_codecOptions["video/theora"] = QStringList();

#endif

    foreach( const QByteArray& codecName, codecCandidates ) {
        QByteArray elementName = m_elementNames[codecName];
        GstElementFactory *factory = gst_element_factory_find(elementName.constData());
        if (factory) {
            m_codecs.append(codecName);
            const gchar *descr = gst_element_factory_get_description(factory);
            m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));

            m_streamTypes.insert(codecName,
                                 CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));

            gst_object_unref(GST_OBJECT(factory));
        }
    }
}

CameraBinVideoEncoder::~CameraBinVideoEncoder()
{
}

QList<QSize> CameraBinVideoEncoder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
{
    if (continuous)
        *continuous = false;

    QPair<int,int> rate = rateAsRational(settings.frameRate());

    //select the closest supported rational rate to settings.frameRate()

    return m_session->supportedResolutions(rate, continuous);
}

QList< qreal > CameraBinVideoEncoder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
{
    if (continuous)
        *continuous = false;

    QList< qreal > res;
    QPair<int,int> rate;

    foreach(rate, m_session->supportedFrameRates(settings.resolution(), continuous)) {
        if (rate.second > 0)
            res << qreal(rate.first)/rate.second;
    }

    return res;
}

QStringList CameraBinVideoEncoder::supportedVideoCodecs() const
{
    return m_codecs;
}

QString CameraBinVideoEncoder::videoCodecDescription(const QString &codecName) const
{
    return m_codecDescriptions.value(codecName);
}

QStringList CameraBinVideoEncoder::supportedEncodingOptions(const QString &codec) const
{
    return m_codecOptions.value(codec);
}

QVariant CameraBinVideoEncoder::encodingOption(const QString &codec, const QString &name) const
{
    return m_options[codec].value(name);
}

void CameraBinVideoEncoder::setEncodingOption(
        const QString &codec, const QString &name, const QVariant &value)
{
    m_options[codec][name] = value;
}

QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const
{
    return m_videoSettings;
}

void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
{
    m_videoSettings = settings;
    m_userSettings = settings;
    emit settingsChanged();
}

void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
{
    m_videoSettings = settings;
}

void CameraBinVideoEncoder::resetActualSettings()
{
    m_videoSettings = m_userSettings;
}

GstElement *CameraBinVideoEncoder::createEncoder()
{
    QString codec = m_videoSettings.codec();
    QByteArray elementName = m_elementNames.value(codec);

    GstElement *encoderElement = gst_element_factory_make( elementName.constData(), "video-encoder");

    if (encoderElement) {
        if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
            QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();

            if (elementName == "x264enc") {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
                int qualityTable[] = {
                    50, //VeryLow
                    35, //Low
                    21, //Normal
                    15, //High
                    8 //VeryHigh
                };
                g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
            } else if (elementName == "xvidenc") {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
                int qualityTable[] = {
                    32, //VeryLow
                    12, //Low
                    5, //Normal
                    3, //High
                    2 //VeryHigh
                };
                int quant = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
            } else if (elementName == "ffenc_mpeg4" ||
                       elementName == "ffenc_mpeg1video" ||
                       elementName == "ffenc_mpeg2video" ) {
                //constant quantizer mode
                g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
                //quant from 1 to 30, default ~3
                double qualityTable[] = {
                    20, //VeryLow
                    8.0, //Low
                    3.0, //Normal
                    2.5, //High
                    2.0 //VeryHigh
                };
                double quant = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
            } else if (elementName == "theoraenc") {
                int qualityTable[] = {
                    8, //VeryLow
                    16, //Low
                    32, //Normal
                    45, //High
                    60 //VeryHigh
                };
                //quality from 0 to 63
                int quality = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
            } else if (elementName == "dsph264enc" ||
                       elementName == "dspmp4venc" ||
                       elementName == "dsph263enc") {
                //only bitrate parameter is supported
                int qualityTable[] = {
                    1000000, //VeryLow
                    2000000, //Low
                    4000000, //Normal
                    8000000, //High
                    16000000 //VeryHigh
                };
                int bitrate = qualityTable[qualityValue];
                g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
            }
        } else {
            int bitrate = m_videoSettings.bitRate();
            if (bitrate > 0) {
                g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
            }
        }

        QMap<QString,QVariant> options = m_options.value(codec);
        QMapIterator<QString,QVariant> it(options);
        while (it.hasNext()) {
            it.next();
            QString option = it.key();
            QVariant value = it.value();

            switch (value.type()) {
            case QVariant::Int:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
                break;
            case QVariant::Bool:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
                break;
            case QVariant::Double:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
                break;
            case QVariant::String:
                g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
                break;
            default:
                qWarning() << "unsupported option type:" << option << value;
                break;
            }

        }
    }

    return encoderElement;
}

QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
{
    if (frameRate > 0.001) {
        //convert to rational number
        QList<int> denumCandidates;
        denumCandidates << 1 << 2 << 3 << 5 << 10 << 25 << 30 << 50 << 100 << 1001 << 1000;

        qreal error = 1.0;
        int num = 1;
        int denum = 1;

        foreach (int curDenum, denumCandidates) {
            int curNum = qRound(frameRate*curDenum);
            qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);

            if (curError < error) {
                error = curError;
                num = curNum;
                denum = curDenum;
            }

            if (curError < 1e-8)
                break;
        }

        return QPair<int,int>(num,denum);
    }

    return QPair<int,int>();
}

QSet<QString> CameraBinVideoEncoder::supportedStreamTypes(const QString &codecName) const
{
    return m_streamTypes.value(codecName);
}
<|endoftext|>