<commit_before>#include "datastream_ROS.h"
#include <QTextStream>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include <thread>
#include <mutex>
#include <chrono>
#include <thread>
#include <QProgressDialog>
#include <QtGlobal>
#include <QApplication>
#include <QProcess>
#include <QSettings>
#include <QFileDialog>
#include <ros/callback_queue.h>
#include <rosbag/bag.h>
#include <topic_tools/shape_shifter.h>

#include "../dialog_select_ros_topics.h"
#include "../rule_editing.h"
#include "../qnodedialog.h"
#include "../shape_shifter_factory.hpp"

DataStreamROS::DataStreamROS():
    _action_saveIntoRosbag(nullptr),
    _node(nullptr)
{
    _enabled = false;
    _running = false;
    _initial_time = std::numeric_limits<double>::max();
    _use_header_timestamp = true;

    _periodic_timer = new QTimer();
    connect( _periodic_timer, &QTimer::timeout,
             this, &DataStreamROS::timerCallback);
}

void DataStreamROS::topicCallback(const topic_tools::ShapeShifter::ConstPtr& msg,
                                  const std::string &topic_name)
{
    if( !_running || !_enabled){
        return;
    }

    using namespace RosIntrospection;
    const auto&  md5sum     =  msg->getMD5Sum();
    const auto&  datatype   =  msg->getDataType();
    const auto&  definition =  msg->getMessageDefinition() ;

      // register the message type
    _parser->registerMessageDefinition(topic_name, ROSType(datatype), definition);
    RosIntrospectionFactory::registerMessage(topic_name, md5sum, datatype, definition );

    if( _using_renaming_rules ){
      for (auto it: _rules)
      {
        _parser->registerRenamingRules( it.first, it.second );
      }
    }

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

    // it is more efficient to recycle this elements
    static std::vector<uint8_t> buffer;
    static FlatMessage flat_container;
    static RenamedValues renamed_value;

    buffer.resize( msg->size() );

    ros::serialization::OStream stream(buffer.data(), buffer.size());
    msg->write(stream);

    // WORKAROUND. There are some problems related to renaming when the character / is
    // used as prefix. We will remove that here.
    //if( topicname_SS.at(0) == '/' ) topicname_SS = SString( topic_name.data() +1,  topic_name.size()-1 );

    _parser->deserializeIntoFlatContainer( topic_name, absl::Span<uint8_t>(buffer), &flat_container, _max_array_size);
    _parser->applyNameTransform( topic_name, flat_container, &renamed_value );

    double msg_time = ros::Time::now().toSec();

    if(_use_header_timestamp)
    {
        const auto header_stamp = FlatContainedContainHeaderStamp(renamed_value);
        if(header_stamp){
            const double time = header_stamp.value();
            if( time > 0 )
            {
              msg_time = time;
            }
        }
    }

    std::lock_guard<std::mutex> lock( mutex() );

    // adding raw serialized msg for future uses.
    // do this before msg_time normalization
    {
        const std::string key = _prefix + topic_name;
        auto plot_pair = dataMap().user_defined.find( key );
        if( plot_pair == dataMap().user_defined.end() )
        {
            PlotDataAnyPtr temp(new PlotDataAny(key.c_str()));
            auto res = dataMap().user_defined.insert( std::make_pair( key, temp ) );
            plot_pair = res.first;
        }
        PlotDataAnyPtr& user_defined_data = plot_pair->second;
        user_defined_data->pushBack( PlotDataAny::Point(msg_time, nonstd::any(std::move(buffer)) ));
    }

    for(auto& it: renamed_value )
    {
        const std::string key = ( _prefix + it.first  );
        const double value = it.second.convert<double>();
        auto plot_it = dataMap().numeric.find(key);
        if( plot_it == dataMap().numeric.end())
        {
            auto res =   dataMap().numeric.insert(
                        std::make_pair( key, std::make_shared<PlotData>(key.c_str()) ));
            plot_it = res.first;
        }
        plot_it->second->pushBack( PlotData::Point(msg_time, value));
    }

    //------------------------------
    {
        int& index = _msg_index[topic_name];
        index++;
        const std::string key = _prefix + topic_name + ("/_MSG_INDEX_") ;
        auto index_it = dataMap().numeric.find(key);
        if( index_it == dataMap().numeric.end())
        {
            auto res = dataMap().numeric.insert(
                        std::make_pair( key, std::make_shared<PlotData>(key.c_str()) ));
            index_it = res.first;
        }
        index_it->second->pushBack( PlotData::Point(msg_time, index) );
    }
}

void DataStreamROS::extractInitialSamples()
{
    using namespace std::chrono;
    milliseconds wait_time_ms(1000);

    QProgressDialog progress_dialog;
    progress_dialog.setLabelText( "Collecting ROS topic samples to understand data layout. ");
    progress_dialog.setRange(0, wait_time_ms.count());
    progress_dialog.setAutoClose(true);
    progress_dialog.setAutoReset(true);

    progress_dialog.show();

    auto start_time = system_clock::now();

    _enabled = true;
    while ( system_clock::now() - start_time < (wait_time_ms) )
    {
        ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
        int i = duration_cast<milliseconds>(system_clock::now() - start_time).count() ;
        progress_dialog.setValue( i );
        QApplication::processEvents();
        if( progress_dialog.wasCanceled() )
        {
            break;
        }
    }
    _enabled = false;

    if( progress_dialog.wasCanceled() == false )
    {
        progress_dialog.cancel();
    }
}

void DataStreamROS::timerCallback()
{
    if( _running && _enabled && ros::master::check() == false
            && !_roscore_disconnection_already_notified)
    {
        auto ret = QMessageBox::warning(nullptr,
                                        tr("Disconnected!"),
                                        tr("The roscore master cannot be detected.\n\n"
                                           "Do you want to try reconnecting to it? \n\n"
                                           "NOTE: if you select CONTINUE, you might need"
                                           " to stop and restart this plugin."),
                                        tr("Stop Plugin"),
                                        tr("Try reconnect"),
                                        tr("Continue"),
                                        0);
        _roscore_disconnection_already_notified = ( ret == 2);
        if( ret == 1)
        {
            this->shutdown();
            _node =  RosManager::getNode();

            if( !_node ){
                emit connectionClosed();
                return;
            }
            subscribe();

            _running = true;
            _enabled = true;
            _spinner = std::make_shared<ros::AsyncSpinner>(1);
            _spinner->start();
            _periodic_timer->start();
        }
        else if( ret == 0)
        {
          this->shutdown();
          emit connectionClosed();
        }
    }
}

void DataStreamROS::saveIntoRosbag()
{
    std::lock_guard<std::mutex> lock( mutex() );
    if( dataMap().user_defined.empty()){
        QMessageBox::warning(0, tr("Warning"), tr("Your buffer is empty. Nothing to save.\n") );
        return;
    }

    QFileDialog saveDialog;
    saveDialog.setAcceptMode(QFileDialog::AcceptSave);
    saveDialog.setDefaultSuffix("bag");
    saveDialog.exec();

    if(saveDialog.result() != QDialog::Accepted || saveDialog.selectedFiles().empty())
    {
        return;
    }

    QString fileName = saveDialog.selectedFiles().first();

    if( fileName.size() > 0)
    {
        rosbag::Bag rosbag(fileName.toStdString(), rosbag::bagmode::Write );

        for (auto it: dataMap().user_defined )
        {
            const std::string& topicname = it.first;
            const PlotDataAnyPtr& plotdata = it.second;

            auto registered_msg_type = RosIntrospectionFactory::get().getShapeShifter(topicname);
            if(!registered_msg_type) continue;

            RosIntrospection::ShapeShifter msg;
            msg.morph(registered_msg_type->getMD5Sum(),
                      registered_msg_type->getDataType(),
                      registered_msg_type->getMessageDefinition());

            for (int i=0; i< plotdata->size(); i++)
            {
                const auto& point = plotdata->at(i);
                const PlotDataAny::TimeType msg_time  = point.x;
                const nonstd::any& type_erased_buffer = point.y;

                if(type_erased_buffer.type() != typeid( std::vector<uint8_t> ))
                {
                  // can't cast to expected type
                  continue;
                }

                std::vector<uint8_t> raw_buffer =  nonstd::any_cast<std::vector<uint8_t>>( type_erased_buffer );
                ros::serialization::IStream stream( raw_buffer.data(), raw_buffer.size() );
                msg.read( stream );

                rosbag.write( topicname, ros::Time(msg_time), msg);
            }
        }
        rosbag.close();

        QProcess process;
        QStringList args;
        args << "reindex" << fileName;
        process.start("rosbag" ,args);
    }
}

void DataStreamROS::subscribe()
{
    _subscribers.clear();

    for (int i=0; i< _default_topic_names.size(); i++ )
    {
        boost::function<void(const topic_tools::ShapeShifter::ConstPtr&) > callback;
        const std::string topic_name = _default_topic_names[i].toStdString();
        callback = [this, topic_name](const topic_tools::ShapeShifter::ConstPtr& msg) -> void
        {
            this->topicCallback(msg, topic_name) ;
        };
        _subscribers.insert( {topic_name, _node->subscribe( topic_name, 0,  callback)}  );
    }
}

bool DataStreamROS::start()
{
    _parser.reset( new RosIntrospection::Parser );
    if( !_node )
    {
        _node =  RosManager::getNode();
    }

    if( !_node ){
        return false;
    }

    {
        std::lock_guard<std::mutex> lock( mutex() );
        dataMap().numeric.clear();
        dataMap().user_defined.clear();
    }
    _initial_time = std::numeric_limits<double>::max();

    using namespace RosIntrospection;

    std::vector<std::pair<QString,QString>> all_topics;
    ros::master::V_TopicInfo topic_infos;
    ros::master::getTopics(topic_infos);
    for (ros::master::TopicInfo topic_info: topic_infos)
    {
        all_topics.push_back(
                    std::make_pair(QString(topic_info.name.c_str()),
                                   QString(topic_info.datatype.c_str()) ) );
    }

    QSettings settings( "IcarusTechnology", "PlotJuggler");

    if( _default_topic_names.empty())
    {
        // if _default_topic_names is empty (xmlLoad didn't work) use QSettings.
        QVariant def = settings.value("DataStreamROS/default_topics");
        if( !def.isNull() && def.isValid())
        {
            _default_topic_names = def.toStringList();
        }
    }

    QTimer timer;
    timer.setSingleShot(false);
    timer.setInterval( 1000);
    timer.start();

    DialogSelectRosTopics dialog(all_topics, _default_topic_names );

    connect( &timer, &QTimer::timeout, [&]()
    {
        all_topics.clear();
        topic_infos.clear();
        ros::master::getTopics(topic_infos);
        for (ros::master::TopicInfo topic_info: topic_infos)
        {
            all_topics.push_back(
                        std::make_pair(QString(topic_info.name.c_str()),
                                       QString(topic_info.datatype.c_str()) ) );
        }
        dialog.updateTopicList(all_topics);
    });

    int res = dialog.exec();

    timer.stop();

    _using_renaming_rules = dialog.checkBoxUseRenamingRules()->isChecked();

    if( res != QDialog::Accepted || dialog.getSelectedItems().empty() )
    {
        return false;
    }

     _default_topic_names = dialog.getSelectedItems();

    settings.setValue("DataStreamROS/default_topics", _default_topic_names);

    // load the rules
    if( dialog.checkBoxUseRenamingRules()->isChecked() ){
        _rules = RuleEditing::getRenamingRules();
    }

    _prefix = dialog.prefix().toStdString();

    _use_header_timestamp = dialog.checkBoxUseHeaderStamp()->isChecked();
    _max_array_size = dialog.maxArraySize();
    //-------------------------

    subscribe();

    _running = true;

    extractInitialSamples();

    _spinner = std::make_shared<ros::AsyncSpinner>(1);
    _spinner->start();

    _periodic_timer->setInterval(500);
    _roscore_disconnection_already_notified = false;
    _periodic_timer->start();
    return true;
}

void DataStreamROS::enableStreaming(bool enable) { _enabled = enable; }

bool DataStreamROS::isStreamingRunning() const { return _running; }

void DataStreamROS::shutdown()
{
    _periodic_timer->stop();
    if(_spinner)
    {
        _spinner->stop();
    }
    for(auto& it: _subscribers)
    {
        it.second.shutdown();
    }
    _subscribers.clear();
    _running = false;
    _enabled = false;
    _node.reset();
    _spinner.reset();
}

DataStreamROS::~DataStreamROS()
{
    shutdown();
}

void DataStreamROS::setParentMenu(QMenu *menu)
{
    _menu = menu;

    _action_saveIntoRosbag = new QAction(QString("Save cached value in a rosbag"), _menu);
    QIcon iconSave;
    iconSave.addFile(QStringLiteral(":/icons/resources/filesave@2x.png"), QSize(26, 26));
    _action_saveIntoRosbag->setIcon(iconSave);

    _menu->addAction( _action_saveIntoRosbag );

    connect( _action_saveIntoRosbag, &QAction::triggered, this, &DataStreamROS::saveIntoRosbag );
}

QDomElement DataStreamROS::xmlSaveState(QDomDocument &doc) const
{
    QString topics_list = _default_topic_names.join(";");
    QDomElement list_elem = doc.createElement("selected_topics");
    list_elem.setAttribute("list", topics_list );
    return list_elem;
}

bool DataStreamROS::xmlLoadState(QDomElement &parent_element)
{
    QDomElement list_elem = parent_element.firstChildElement( "selected_topics" );
    if( !list_elem.isNull()    )
    {
        if( list_elem.hasAttribute("list") )
        {
            QString topics_list = list_elem.attribute("list");
            _default_topic_names = topics_list.split(";", QString::SkipEmptyParts);
            return true;
        }
    }
    return false;
}

<commit_msg>add transport hint<commit_after>#include "datastream_ROS.h"
#include <QTextStream>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include <thread>
#include <mutex>
#include <chrono>
#include <thread>
#include <QProgressDialog>
#include <QtGlobal>
#include <QApplication>
#include <QProcess>
#include <QSettings>
#include <QFileDialog>
#include <ros/callback_queue.h>
#include <rosbag/bag.h>
#include <topic_tools/shape_shifter.h>
#include <ros/transport_hints.h>

#include "../dialog_select_ros_topics.h"
#include "../rule_editing.h"
#include "../qnodedialog.h"
#include "../shape_shifter_factory.hpp"

DataStreamROS::DataStreamROS():
    _action_saveIntoRosbag(nullptr),
    _node(nullptr)
{
    _enabled = false;
    _running = false;
    _initial_time = std::numeric_limits<double>::max();
    _use_header_timestamp = true;

    _periodic_timer = new QTimer();
    connect( _periodic_timer, &QTimer::timeout,
             this, &DataStreamROS::timerCallback);
}

void DataStreamROS::topicCallback(const topic_tools::ShapeShifter::ConstPtr& msg,
                                  const std::string &topic_name)
{
    if( !_running || !_enabled){
        return;
    }

    using namespace RosIntrospection;
    const auto&  md5sum     =  msg->getMD5Sum();
    const auto&  datatype   =  msg->getDataType();
    const auto&  definition =  msg->getMessageDefinition() ;

      // register the message type
    _parser->registerMessageDefinition(topic_name, ROSType(datatype), definition);
    RosIntrospectionFactory::registerMessage(topic_name, md5sum, datatype, definition );

    if( _using_renaming_rules ){
      for (auto it: _rules)
      {
        _parser->registerRenamingRules( it.first, it.second );
      }
    }

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

    // it is more efficient to recycle this elements
    static std::vector<uint8_t> buffer;
    static FlatMessage flat_container;
    static RenamedValues renamed_value;

    buffer.resize( msg->size() );

    ros::serialization::OStream stream(buffer.data(), buffer.size());
    msg->write(stream);

    // WORKAROUND. There are some problems related to renaming when the character / is
    // used as prefix. We will remove that here.
    //if( topicname_SS.at(0) == '/' ) topicname_SS = SString( topic_name.data() +1,  topic_name.size()-1 );

    _parser->deserializeIntoFlatContainer( topic_name, absl::Span<uint8_t>(buffer), &flat_container, _max_array_size);
    _parser->applyNameTransform( topic_name, flat_container, &renamed_value );

    double msg_time = ros::Time::now().toSec();

    if(_use_header_timestamp)
    {
        const auto header_stamp = FlatContainedContainHeaderStamp(renamed_value);
        if(header_stamp){
            const double time = header_stamp.value();
            if( time > 0 )
            {
              msg_time = time;
            }
        }
    }

    std::lock_guard<std::mutex> lock( mutex() );

    // adding raw serialized msg for future uses.
    // do this before msg_time normalization
    {
        const std::string key = _prefix + topic_name;
        auto plot_pair = dataMap().user_defined.find( key );
        if( plot_pair == dataMap().user_defined.end() )
        {
            PlotDataAnyPtr temp(new PlotDataAny(key.c_str()));
            auto res = dataMap().user_defined.insert( std::make_pair( key, temp ) );
            plot_pair = res.first;
        }
        PlotDataAnyPtr& user_defined_data = plot_pair->second;
        user_defined_data->pushBack( PlotDataAny::Point(msg_time, nonstd::any(std::move(buffer)) ));
    }

    for(auto& it: renamed_value )
    {
        const std::string key = ( _prefix + it.first  );
        const double value = it.second.convert<double>();
        auto plot_it = dataMap().numeric.find(key);
        if( plot_it == dataMap().numeric.end())
        {
            auto res =   dataMap().numeric.insert(
                        std::make_pair( key, std::make_shared<PlotData>(key.c_str()) ));
            plot_it = res.first;
        }
        plot_it->second->pushBack( PlotData::Point(msg_time, value));
    }

    //------------------------------
    {
        int& index = _msg_index[topic_name];
        index++;
        const std::string key = _prefix + topic_name + ("/_MSG_INDEX_") ;
        auto index_it = dataMap().numeric.find(key);
        if( index_it == dataMap().numeric.end())
        {
            auto res = dataMap().numeric.insert(
                        std::make_pair( key, std::make_shared<PlotData>(key.c_str()) ));
            index_it = res.first;
        }
        index_it->second->pushBack( PlotData::Point(msg_time, index) );
    }
}

void DataStreamROS::extractInitialSamples()
{
    using namespace std::chrono;
    milliseconds wait_time_ms(1000);

    QProgressDialog progress_dialog;
    progress_dialog.setLabelText( "Collecting ROS topic samples to understand data layout. ");
    progress_dialog.setRange(0, wait_time_ms.count());
    progress_dialog.setAutoClose(true);
    progress_dialog.setAutoReset(true);

    progress_dialog.show();

    auto start_time = system_clock::now();

    _enabled = true;
    while ( system_clock::now() - start_time < (wait_time_ms) )
    {
        ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
        int i = duration_cast<milliseconds>(system_clock::now() - start_time).count() ;
        progress_dialog.setValue( i );
        QApplication::processEvents();
        if( progress_dialog.wasCanceled() )
        {
            break;
        }
    }
    _enabled = false;

    if( progress_dialog.wasCanceled() == false )
    {
        progress_dialog.cancel();
    }
}

void DataStreamROS::timerCallback()
{
    if( _running && _enabled && ros::master::check() == false
            && !_roscore_disconnection_already_notified)
    {
        auto ret = QMessageBox::warning(nullptr,
                                        tr("Disconnected!"),
                                        tr("The roscore master cannot be detected.\n\n"
                                           "Do you want to try reconnecting to it? \n\n"
                                           "NOTE: if you select CONTINUE, you might need"
                                           " to stop and restart this plugin."),
                                        tr("Stop Plugin"),
                                        tr("Try reconnect"),
                                        tr("Continue"),
                                        0);
        _roscore_disconnection_already_notified = ( ret == 2);
        if( ret == 1)
        {
            this->shutdown();
            _node =  RosManager::getNode();

            if( !_node ){
                emit connectionClosed();
                return;
            }
            subscribe();

            _running = true;
            _enabled = true;
            _spinner = std::make_shared<ros::AsyncSpinner>(1);
            _spinner->start();
            _periodic_timer->start();
        }
        else if( ret == 0)
        {
          this->shutdown();
          emit connectionClosed();
        }
    }
}

void DataStreamROS::saveIntoRosbag()
{
    std::lock_guard<std::mutex> lock( mutex() );
    if( dataMap().user_defined.empty()){
        QMessageBox::warning(0, tr("Warning"), tr("Your buffer is empty. Nothing to save.\n") );
        return;
    }

    QFileDialog saveDialog;
    saveDialog.setAcceptMode(QFileDialog::AcceptSave);
    saveDialog.setDefaultSuffix("bag");
    saveDialog.exec();

    if(saveDialog.result() != QDialog::Accepted || saveDialog.selectedFiles().empty())
    {
        return;
    }

    QString fileName = saveDialog.selectedFiles().first();

    if( fileName.size() > 0)
    {
        rosbag::Bag rosbag(fileName.toStdString(), rosbag::bagmode::Write );

        for (auto it: dataMap().user_defined )
        {
            const std::string& topicname = it.first;
            const PlotDataAnyPtr& plotdata = it.second;

            auto registered_msg_type = RosIntrospectionFactory::get().getShapeShifter(topicname);
            if(!registered_msg_type) continue;

            RosIntrospection::ShapeShifter msg;
            msg.morph(registered_msg_type->getMD5Sum(),
                      registered_msg_type->getDataType(),
                      registered_msg_type->getMessageDefinition());

            for (int i=0; i< plotdata->size(); i++)
            {
                const auto& point = plotdata->at(i);
                const PlotDataAny::TimeType msg_time  = point.x;
                const nonstd::any& type_erased_buffer = point.y;

                if(type_erased_buffer.type() != typeid( std::vector<uint8_t> ))
                {
                  // can't cast to expected type
                  continue;
                }

                std::vector<uint8_t> raw_buffer =  nonstd::any_cast<std::vector<uint8_t>>( type_erased_buffer );
                ros::serialization::IStream stream( raw_buffer.data(), raw_buffer.size() );
                msg.read( stream );

                rosbag.write( topicname, ros::Time(msg_time), msg);
            }
        }
        rosbag.close();

        QProcess process;
        QStringList args;
        args << "reindex" << fileName;
        process.start("rosbag" ,args);
    }
}

void DataStreamROS::subscribe()
{
    _subscribers.clear();

    for (int i=0; i< _default_topic_names.size(); i++ )
    {
        const std::string topic_name = _default_topic_names[i].toStdString();
        boost::function<void(const topic_tools::ShapeShifter::ConstPtr&) > callback;
        callback = [this, topic_name](const topic_tools::ShapeShifter::ConstPtr& msg) -> void
        {
            this->topicCallback(msg, topic_name) ;
        };

        ros::SubscribeOptions ops;
        ops.initByFullCallbackType(topic_name, 1, callback);
        ops.transport_hints = ros::TransportHints().tcpNoDelay();

        _subscribers.insert( {topic_name, _node->subscribe(ops) }  );
    }
}

bool DataStreamROS::start()
{
    _parser.reset( new RosIntrospection::Parser );
    if( !_node )
    {
        _node =  RosManager::getNode();
    }

    if( !_node ){
        return false;
    }

    {
        std::lock_guard<std::mutex> lock( mutex() );
        dataMap().numeric.clear();
        dataMap().user_defined.clear();
    }
    _initial_time = std::numeric_limits<double>::max();

    using namespace RosIntrospection;

    std::vector<std::pair<QString,QString>> all_topics;
    ros::master::V_TopicInfo topic_infos;
    ros::master::getTopics(topic_infos);
    for (ros::master::TopicInfo topic_info: topic_infos)
    {
        all_topics.push_back(
                    std::make_pair(QString(topic_info.name.c_str()),
                                   QString(topic_info.datatype.c_str()) ) );
    }

    QSettings settings( "IcarusTechnology", "PlotJuggler");

    if( _default_topic_names.empty())
    {
        // if _default_topic_names is empty (xmlLoad didn't work) use QSettings.
        QVariant def = settings.value("DataStreamROS/default_topics");
        if( !def.isNull() && def.isValid())
        {
            _default_topic_names = def.toStringList();
        }
    }

    QTimer timer;
    timer.setSingleShot(false);
    timer.setInterval( 1000);
    timer.start();

    DialogSelectRosTopics dialog(all_topics, _default_topic_names );

    connect( &timer, &QTimer::timeout, [&]()
    {
        all_topics.clear();
        topic_infos.clear();
        ros::master::getTopics(topic_infos);
        for (ros::master::TopicInfo topic_info: topic_infos)
        {
            all_topics.push_back(
                        std::make_pair(QString(topic_info.name.c_str()),
                                       QString(topic_info.datatype.c_str()) ) );
        }
        dialog.updateTopicList(all_topics);
    });

    int res = dialog.exec();

    timer.stop();

    _using_renaming_rules = dialog.checkBoxUseRenamingRules()->isChecked();

    if( res != QDialog::Accepted || dialog.getSelectedItems().empty() )
    {
        return false;
    }

     _default_topic_names = dialog.getSelectedItems();

    settings.setValue("DataStreamROS/default_topics", _default_topic_names);

    // load the rules
    if( dialog.checkBoxUseRenamingRules()->isChecked() ){
        _rules = RuleEditing::getRenamingRules();
    }

    _prefix = dialog.prefix().toStdString();

    _use_header_timestamp = dialog.checkBoxUseHeaderStamp()->isChecked();
    _max_array_size = dialog.maxArraySize();
    //-------------------------

    subscribe();

    _running = true;

    extractInitialSamples();

    _spinner = std::make_shared<ros::AsyncSpinner>(1);
    _spinner->start();

    _periodic_timer->setInterval(500);
    _roscore_disconnection_already_notified = false;
    _periodic_timer->start();
    return true;
}

void DataStreamROS::enableStreaming(bool enable) { _enabled = enable; }

bool DataStreamROS::isStreamingRunning() const { return _running; }

void DataStreamROS::shutdown()
{
    _periodic_timer->stop();
    if(_spinner)
    {
        _spinner->stop();
    }
    for(auto& it: _subscribers)
    {
        it.second.shutdown();
    }
    _subscribers.clear();
    _running = false;
    _enabled = false;
    _node.reset();
    _spinner.reset();
}

DataStreamROS::~DataStreamROS()
{
    shutdown();
}

void DataStreamROS::setParentMenu(QMenu *menu)
{
    _menu = menu;

    _action_saveIntoRosbag = new QAction(QString("Save cached value in a rosbag"), _menu);
    QIcon iconSave;
    iconSave.addFile(QStringLiteral(":/icons/resources/filesave@2x.png"), QSize(26, 26));
    _action_saveIntoRosbag->setIcon(iconSave);

    _menu->addAction( _action_saveIntoRosbag );

    connect( _action_saveIntoRosbag, &QAction::triggered, this, &DataStreamROS::saveIntoRosbag );
}

QDomElement DataStreamROS::xmlSaveState(QDomDocument &doc) const
{
    QString topics_list = _default_topic_names.join(";");
    QDomElement list_elem = doc.createElement("selected_topics");
    list_elem.setAttribute("list", topics_list );
    return list_elem;
}

bool DataStreamROS::xmlLoadState(QDomElement &parent_element)
{
    QDomElement list_elem = parent_element.firstChildElement( "selected_topics" );
    if( !list_elem.isNull()    )
    {
        if( list_elem.hasAttribute("list") )
        {
            QString topics_list = list_elem.attribute("list");
            _default_topic_names = topics_list.split(";", QString::SkipEmptyParts);
            return true;
        }
    }
    return false;
}

<|endoftext|>


<commit_before>//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp ------- DAG Address
//Analysis ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//

#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"

namespace llvm {

bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
                                     const SelectionDAG &DAG, int64_t &Off) {
  // Initial Offset difference.
  Off = Other.Offset - Offset;

  if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
    // Trivial match.
    if (Other.Base == Base)
      return true;

    // Match GlobalAddresses
    if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
      if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
        if (A->getGlobal() == B->getGlobal()) {
          Off += B->getOffset() - A->getOffset();
          return true;
        }

    const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();

    // Match non-equal FrameIndexes - a FrameIndex stemming from an
    // alloca will not have it's ObjectOffset set until post-DAG and
    // as such we must assume the two framesIndices are incomparable.
    if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
      if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
        if (!MFI.getObjectAllocation(A->getIndex()) &&
            !MFI.getObjectAllocation(B->getIndex())) {
          Off += MFI.getObjectOffset(B->getIndex()) -
                 MFI.getObjectOffset(A->getIndex());
          return true;
        }
  }
  return false;
}

/// Parses tree in Ptr for base, index, offset addresses.
BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
  // (((B + I*M) + c)) + c ...
  SDValue Base = Ptr;
  SDValue Index = SDValue();
  int64_t Offset = 0;
  bool IsIndexSignExt = false;

  // Consume constant adds
  while (Base->getOpcode() == ISD::ADD &&
         isa<ConstantSDNode>(Base->getOperand(1))) {
    int64_t POffset = cast<ConstantSDNode>(Base->getOperand(1))->getSExtValue();
    Offset += POffset;
    Base = Base->getOperand(0);
  }

  if (Base->getOpcode() == ISD::ADD) {
    // TODO: The following code appears to be needless as it just
    //       bails on some Ptrs early, reducing the cases where we
    //       find equivalence. We should be able to remove this.
    // Inside a loop the current BASE pointer is calculated using an ADD and a
    // MUL instruction. In this case Base is the actual BASE pointer.
    // (i64 add (i64 %array_ptr)
    //          (i64 mul (i64 %induction_var)
    //                   (i64 %element_size)))
    if (Base->getOperand(1)->getOpcode() == ISD::MUL)
      return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);

    // Look at Base + Index + Offset cases.
    Index = Base->getOperand(1);
    SDValue PotentialBase = Base->getOperand(0);

    // Skip signextends.
    if (Index->getOpcode() == ISD::SIGN_EXTEND) {
      Index = Index->getOperand(0);
      IsIndexSignExt = true;
    }

    // Check if Index Offset pattern
    if (Index->getOpcode() != ISD::ADD ||
        !isa<ConstantSDNode>(Index->getOperand(1)))
      return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);

    Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
    Index = Index->getOperand(0);
    if (Index->getOpcode() == ISD::SIGN_EXTEND) {
      Index = Index->getOperand(0);
      IsIndexSignExt = true;
    } else
      IsIndexSignExt = false;
    Base = PotentialBase;
  }
  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
}
} // end namespace llvm
<commit_msg>[DAG] Fixed predicate for determining when two frame indices addresses are comparable. NFCI.<commit_after>//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp ------- DAG Address
//Analysis ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//

#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"

namespace llvm {

bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
                                     const SelectionDAG &DAG, int64_t &Off) {
  // Initial Offset difference.
  Off = Other.Offset - Offset;

  if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
    // Trivial match.
    if (Other.Base == Base)
      return true;

    // Match GlobalAddresses
    if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
      if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
        if (A->getGlobal() == B->getGlobal()) {
          Off += B->getOffset() - A->getOffset();
          return true;
        }

    const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();

    // Match non-equal FrameIndexes - If both frame indices are fixed
    // we know their relative offsets and can compare them. Otherwise
    // we must be conservative.
    if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
      if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
        if (MFI.isFixedObjectIndex(A->getIndex()) &&
            MFI.isFixedObjectIndex(B->getIndex())) {
          Off += MFI.getObjectOffset(B->getIndex()) -
                 MFI.getObjectOffset(A->getIndex());
          return true;
        }
  }
  return false;
}

/// Parses tree in Ptr for base, index, offset addresses.
BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
  // (((B + I*M) + c)) + c ...
  SDValue Base = Ptr;
  SDValue Index = SDValue();
  int64_t Offset = 0;
  bool IsIndexSignExt = false;

  // Consume constant adds
  while (Base->getOpcode() == ISD::ADD &&
         isa<ConstantSDNode>(Base->getOperand(1))) {
    int64_t POffset = cast<ConstantSDNode>(Base->getOperand(1))->getSExtValue();
    Offset += POffset;
    Base = Base->getOperand(0);
  }

  if (Base->getOpcode() == ISD::ADD) {
    // TODO: The following code appears to be needless as it just
    //       bails on some Ptrs early, reducing the cases where we
    //       find equivalence. We should be able to remove this.
    // Inside a loop the current BASE pointer is calculated using an ADD and a
    // MUL instruction. In this case Base is the actual BASE pointer.
    // (i64 add (i64 %array_ptr)
    //          (i64 mul (i64 %induction_var)
    //                   (i64 %element_size)))
    if (Base->getOperand(1)->getOpcode() == ISD::MUL)
      return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);

    // Look at Base + Index + Offset cases.
    Index = Base->getOperand(1);
    SDValue PotentialBase = Base->getOperand(0);

    // Skip signextends.
    if (Index->getOpcode() == ISD::SIGN_EXTEND) {
      Index = Index->getOperand(0);
      IsIndexSignExt = true;
    }

    // Check if Index Offset pattern
    if (Index->getOpcode() != ISD::ADD ||
        !isa<ConstantSDNode>(Index->getOperand(1)))
      return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);

    Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
    Index = Index->getOperand(0);
    if (Index->getOpcode() == ISD::SIGN_EXTEND) {
      Index = Index->getOperand(0);
      IsIndexSignExt = true;
    } else
      IsIndexSignExt = false;
    Base = PotentialBase;
  }
  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
}
} // end namespace llvm
<|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.
//
// Broker RPC Server implementation.

#include "ceee/ie/broker/broker_rpc_server.h"

#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/process_util.h"
#include "broker_rpc_lib.h"  // NOLINT
#include "ceee/common/com_utils.h"
#include "ceee/ie/broker/broker_module_util.h"
#include "ceee/ie/broker/broker_rpc_utils.h"
#include "ceee/ie/broker/chrome_postman.h"

namespace {
// This lock ensures that histograms created by the broker are thread safe.
// The histograms created here can be initialized on multiple threads.
Lock g_metrics_lock;

RPC_STATUS PrepareEndpoint(std::wstring endpoint) {
  std::wstring protocol = kRpcProtocol;
  DCHECK(!protocol.empty());
  DCHECK(!endpoint.empty());
  if (protocol.empty() || endpoint.empty())
    return false;
  VLOG(1) << "RPC server is starting. Endpoint: " << endpoint;
  // Tell RPC runtime to use local interprocess communication for given
  // end point.
  RPC_STATUS status = ::RpcServerUseProtseqEp(
      reinterpret_cast<RPC_WSTR>(&protocol[0]),
      RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
      reinterpret_cast<RPC_WSTR>(&endpoint[0]),
      NULL);
  LOG_IF(ERROR, RPC_S_OK != status && RPC_S_DUPLICATE_ENDPOINT != status) <<
      "Failed to set protocol for RPC end point. RPC_STATUS=0x" <<
      com::LogWe(status);
  // This is not an error because unittest may start several servers. For
  // ceee_broker this is an error because we should not have several instances
  // of broker for the same endpoint. However BrokerRpcServer will fail anyway
  // while starting to listen.
  if (RPC_S_DUPLICATE_ENDPOINT == status)
    status = RPC_S_OK;
  return status;
}

}  // namespace

BrokerRpcServer::BrokerRpcServer()
    : is_started_(false),
      current_thread_(::GetCurrentThreadId()) {
}

BrokerRpcServer::~BrokerRpcServer() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  Stop();
}

bool BrokerRpcServer::Start() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());

  if (is_started())
    return true;

  std::wstring endpoint = GetRpcEndpointAddress();
  RPC_STATUS status = PrepareEndpoint(endpoint);

  if (RPC_S_OK == status) {
    // Register RPC interface with the RPC runtime.
    status = ::RpcServerRegisterIfEx(BrokerRpcServer_CeeeBroker_v1_1_s_ifspec,
        NULL, NULL, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL);
    LOG_IF(ERROR, RPC_S_OK != status) <<
      "Failed to register RPC interface. RPC_STATUS=0x" << com::LogWe(status);
    if (RPC_S_OK == status) {
      // Start listen for RPC calls.
      status = ::RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
      LOG_IF(ERROR, RPC_S_OK != status) <<
          "Failed to start listening. RPC_STATUS=0x" << com::LogWe(status);
      if (RPC_S_OK == status) {
        VLOG(1) << "RPC server is started. Endpoint: " << endpoint;
        is_started_ = true;
      }
    }
  }
  if (!is_started())
    Stop();

  return is_started();
}

bool BrokerRpcServer::Stop() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  is_started_ = false;
  // Stop server listening for RPC.
  RPC_STATUS status = ::RpcMgmtStopServerListening(NULL);
  LOG_IF(WARNING, RPC_S_OK != status && RPC_S_NOT_LISTENING != status) <<
      "Failed to stop listening. RPC_STATUS=0x" << com::LogWe(status);
  // Wait while server stops listening threads.
  status = ::RpcMgmtWaitServerListen();
  LOG_IF(WARNING, RPC_S_OK != status && RPC_S_NOT_LISTENING != status) <<
      "Failed to wait server listen. RPC_STATUS=0x" << com::LogWe(status);
  // Unregister RPC interface.
  status = ::RpcServerUnregisterIf(
      BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, NULL, FALSE);
  LOG_IF(WARNING, RPC_S_OK != status || RPC_S_UNKNOWN_MGR_TYPE != status ||
                  RPC_S_UNKNOWN_IF != status) <<
      "Failed to unregister interface. RPC_STATUS=0x" << com::LogWe(status);

  return RPC_S_OK == status;
}

bool BrokerRpcServer::is_started() const {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  return is_started_;
}

static base::AtomicSequenceNumber current_broker_rpc_context(
    base::LINKER_INITIALIZED);

BrokerContextHandle BrokerRpcServer_Connect(handle_t binding_handle) {
  // TODO(vitalybuka@google.com): Add client identity check.
  ceee_module_util::LockModule();
  return reinterpret_cast<void*>(current_broker_rpc_context.GetNext() + 1);
}

void BrokerRpcServer_Disconnect(
    handle_t binding_handle,
    BrokerContextHandle* context) {
  DCHECK(context != NULL);
  if (context)
    *context = NULL;
  ceee_module_util::UnlockModule();
}

// Called when client process terminated without releasing context handle.
void __RPC_USER BrokerContextHandle_rundown(BrokerContextHandle context) {
  DCHECK(context != NULL);
  ceee_module_util::UnlockModule();
}

void BrokerRpcServer_FireEvent(
    handle_t binding_handle,
    BrokerContextHandle context,
    const char* event_name,
    const char* event_args) {
  DCHECK(ChromePostman::GetInstance());
  if (ChromePostman::GetInstance())
    ChromePostman::GetInstance()->FireEvent(event_name, event_args);
}

void BrokerRpcServer_SendUmaHistogramTimes(handle_t binding_handle,
                                           const char* name,
                                           int sample) {
  // We can't unfortunately use the HISTOGRAM_*_TIMES here because they use
  // static variables to save time.
  AutoLock lock(g_metrics_lock);
  scoped_refptr<base::Histogram> counter =
      base::Histogram::FactoryTimeGet(name,
          base::TimeDelta::FromMilliseconds(1),
          base::TimeDelta::FromSeconds(10),
          50, base::Histogram::kUmaTargetedHistogramFlag);
  DCHECK_EQ(name, counter->histogram_name());
  if (counter.get())
    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
}

void BrokerRpcServer_SendUmaHistogramData(handle_t binding_handle,
                                          const char* name,
                                          int sample,
                                          int min, int max,
                                          int bucket_count) {
  // We can't unfortunately use the HISTOGRAM_*_COUNT here because they use
  // static variables to save time.
  AutoLock lock(g_metrics_lock);
  scoped_refptr<base::Histogram> counter =
      base::Histogram::FactoryGet(name, min, max, bucket_count,
          base::Histogram::kUmaTargetedHistogramFlag);
  DCHECK_EQ(name, counter->histogram_name());
  if (counter.get())
    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
}
<commit_msg>Fix LOG_IF check.<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.
//
// Broker RPC Server implementation.

#include "ceee/ie/broker/broker_rpc_server.h"

#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/process_util.h"
#include "broker_rpc_lib.h"  // NOLINT
#include "ceee/common/com_utils.h"
#include "ceee/ie/broker/broker_module_util.h"
#include "ceee/ie/broker/broker_rpc_utils.h"
#include "ceee/ie/broker/chrome_postman.h"

namespace {
// This lock ensures that histograms created by the broker are thread safe.
// The histograms created here can be initialized on multiple threads.
Lock g_metrics_lock;

RPC_STATUS PrepareEndpoint(std::wstring endpoint) {
  std::wstring protocol = kRpcProtocol;
  DCHECK(!protocol.empty());
  DCHECK(!endpoint.empty());
  if (protocol.empty() || endpoint.empty())
    return false;
  VLOG(1) << "RPC server is starting. Endpoint: " << endpoint;
  // Tell RPC runtime to use local interprocess communication for given
  // end point.
  RPC_STATUS status = ::RpcServerUseProtseqEp(
      reinterpret_cast<RPC_WSTR>(&protocol[0]),
      RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
      reinterpret_cast<RPC_WSTR>(&endpoint[0]),
      NULL);
  LOG_IF(ERROR, RPC_S_OK != status && RPC_S_DUPLICATE_ENDPOINT != status) <<
      "Failed to set protocol for RPC end point. RPC_STATUS=0x" <<
      com::LogWe(status);
  // This is not an error because unittest may start several servers. For
  // ceee_broker this is an error because we should not have several instances
  // of broker for the same endpoint. However BrokerRpcServer will fail anyway
  // while starting to listen.
  if (RPC_S_DUPLICATE_ENDPOINT == status)
    status = RPC_S_OK;
  return status;
}

}  // namespace

BrokerRpcServer::BrokerRpcServer()
    : is_started_(false),
      current_thread_(::GetCurrentThreadId()) {
}

BrokerRpcServer::~BrokerRpcServer() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  Stop();
}

bool BrokerRpcServer::Start() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());

  if (is_started())
    return true;

  std::wstring endpoint = GetRpcEndpointAddress();
  RPC_STATUS status = PrepareEndpoint(endpoint);

  if (RPC_S_OK == status) {
    // Register RPC interface with the RPC runtime.
    status = ::RpcServerRegisterIfEx(BrokerRpcServer_CeeeBroker_v1_1_s_ifspec,
        NULL, NULL, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL);
    LOG_IF(ERROR, RPC_S_OK != status) <<
      "Failed to register RPC interface. RPC_STATUS=0x" << com::LogWe(status);
    if (RPC_S_OK == status) {
      // Start listen for RPC calls.
      status = ::RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
      LOG_IF(ERROR, RPC_S_OK != status) <<
          "Failed to start listening. RPC_STATUS=0x" << com::LogWe(status);
      if (RPC_S_OK == status) {
        VLOG(1) << "RPC server is started. Endpoint: " << endpoint;
        is_started_ = true;
      }
    }
  }
  if (!is_started())
    Stop();

  return is_started();
}

bool BrokerRpcServer::Stop() {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  is_started_ = false;
  // Stop server listening for RPC.
  RPC_STATUS status = ::RpcMgmtStopServerListening(NULL);
  LOG_IF(WARNING, RPC_S_OK != status && RPC_S_NOT_LISTENING != status) <<
      "Failed to stop listening. RPC_STATUS=0x" << com::LogWe(status);
  // Wait while server stops listening threads.
  status = ::RpcMgmtWaitServerListen();
  LOG_IF(WARNING, RPC_S_OK != status && RPC_S_NOT_LISTENING != status) <<
      "Failed to wait server listen. RPC_STATUS=0x" << com::LogWe(status);
  // Unregister RPC interface.
  status = ::RpcServerUnregisterIf(
      BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, NULL, FALSE);
  LOG_IF(WARNING, RPC_S_OK != status && RPC_S_UNKNOWN_MGR_TYPE != status &&
                  RPC_S_UNKNOWN_IF != status) <<
      "Failed to unregister interface. RPC_STATUS=0x" << com::LogWe(status);

  return RPC_S_OK == status;
}

bool BrokerRpcServer::is_started() const {
  DCHECK(current_thread_ == ::GetCurrentThreadId());
  return is_started_;
}

static base::AtomicSequenceNumber current_broker_rpc_context(
    base::LINKER_INITIALIZED);

BrokerContextHandle BrokerRpcServer_Connect(handle_t binding_handle) {
  // TODO(vitalybuka@google.com): Add client identity check.
  ceee_module_util::LockModule();
  return reinterpret_cast<void*>(current_broker_rpc_context.GetNext() + 1);
}

void BrokerRpcServer_Disconnect(
    handle_t binding_handle,
    BrokerContextHandle* context) {
  DCHECK(context != NULL);
  if (context)
    *context = NULL;
  ceee_module_util::UnlockModule();
}

// Called when client process terminated without releasing context handle.
void __RPC_USER BrokerContextHandle_rundown(BrokerContextHandle context) {
  DCHECK(context != NULL);
  ceee_module_util::UnlockModule();
}

void BrokerRpcServer_FireEvent(
    handle_t binding_handle,
    BrokerContextHandle context,
    const char* event_name,
    const char* event_args) {
  DCHECK(ChromePostman::GetInstance());
  if (ChromePostman::GetInstance())
    ChromePostman::GetInstance()->FireEvent(event_name, event_args);
}

void BrokerRpcServer_SendUmaHistogramTimes(handle_t binding_handle,
                                           const char* name,
                                           int sample) {
  // We can't unfortunately use the HISTOGRAM_*_TIMES here because they use
  // static variables to save time.
  AutoLock lock(g_metrics_lock);
  scoped_refptr<base::Histogram> counter =
      base::Histogram::FactoryTimeGet(name,
          base::TimeDelta::FromMilliseconds(1),
          base::TimeDelta::FromSeconds(10),
          50, base::Histogram::kUmaTargetedHistogramFlag);
  DCHECK_EQ(name, counter->histogram_name());
  if (counter.get())
    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
}

void BrokerRpcServer_SendUmaHistogramData(handle_t binding_handle,
                                          const char* name,
                                          int sample,
                                          int min, int max,
                                          int bucket_count) {
  // We can't unfortunately use the HISTOGRAM_*_COUNT here because they use
  // static variables to save time.
  AutoLock lock(g_metrics_lock);
  scoped_refptr<base::Histogram> counter =
      base::Histogram::FactoryGet(name, min, max, bucket_count,
          base::Histogram::kUmaTargetedHistogramFlag);
  DCHECK_EQ(name, counter->histogram_name());
  if (counter.get())
    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
}
<|endoftext|>


<commit_before>#include "openlocationcode.h"
#include "codearea.h"

#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>

#include "gtest/gtest.h"

namespace openlocationcode {
namespace internal {
namespace {

TEST(ParameterChecks, PairCodeLengthIsEven) {
  EXPECT_EQ(0, internal::kPairCodeLength % 2);
}

TEST(ParameterChecks, AlphabetIsOrdered) {
  char last = 0;
  for (size_t i = 0; i < internal::kEncodingBase; i++) {
    EXPECT_TRUE(internal::kAlphabet[i] > last);
    last = internal::kAlphabet[i];
  }
}

TEST(ParameterChecks, SeparatorPositionValid) {
  EXPECT_TRUE(internal::kSeparatorPosition <= internal::kPairCodeLength);
}

TEST(ParameterChecks, ShortenDegreesValid) {
  EXPECT_TRUE(internal::kMinShortenDegrees >= internal::kGridSizeDegrees);
}

}  // namespace
}  // namespace internal

namespace {

std::vector<std::vector<std::string>> ParseCsv(std::string path_to_file) {
  std::vector<std::vector<std::string>> csv_records;
  std::string line;

  std::ifstream input_stream(path_to_file, std::ifstream::binary);
  while (std::getline(input_stream, line)) {
    // Ignore comments in the file
    if (line.at(0) == '#') {
      continue;
    }
    std::vector<std::string> line_records;
    std::stringstream lineStream(line);
    std::string cell;
    while (std::getline(lineStream, cell, ',')) {
      line_records.push_back(cell);
    }
    csv_records.push_back(line_records);
  }
  EXPECT_GT(csv_records.size(), 0);
  return csv_records;
}

struct EncodingTestData {
  std::string code;
  double lat_deg;
  double lng_deg;
  double lo_lat_deg;
  double lo_lng_deg;
  double hi_lat_deg;
  double hi_lng_deg;
};

class EncodingChecks : public ::testing::TestWithParam<EncodingTestData> {};

const std::string kEncodingTestsFile = "test_data/encodingTests.csv";

std::vector<EncodingTestData> GetEncodingDataFromCsv() {
  std::vector<EncodingTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kEncodingTestsFile);
  char *stopstring;
  for (size_t i = 0; i < csv_records.size(); i++) {
    EncodingTestData test_data = {};
    test_data.code = csv_records[i][0];
    test_data.lat_deg = strtod(csv_records[i][1].c_str(), &stopstring);
    test_data.lng_deg = strtod(csv_records[i][2].c_str(), &stopstring);
    test_data.lo_lat_deg = strtod(csv_records[i][3].c_str(), &stopstring);
    test_data.lo_lng_deg = strtod(csv_records[i][4].c_str(), &stopstring);
    test_data.hi_lat_deg = strtod(csv_records[i][5].c_str(), &stopstring);
    test_data.hi_lng_deg = strtod(csv_records[i][6].c_str(), &stopstring);
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(EncodingChecks, Encode) {
  EncodingTestData test_data = GetParam();
  CodeArea expected_rect =
      CodeArea(test_data.lo_lat_deg, test_data.lo_lng_deg, test_data.hi_lat_deg,
               test_data.hi_lng_deg, CodeLength(test_data.code));
  LatLng lat_lng = LatLng{test_data.lat_deg, test_data.lng_deg};
  // Encode the test location and make sure we get the expected code.
  std::string actual_code = Encode(lat_lng, CodeLength(test_data.code));
  EXPECT_EQ(test_data.code, actual_code);
  // Now decode the code and check we get the correct coordinates.
  CodeArea actual_rect = Decode(test_data.code);
  EXPECT_NEAR(expected_rect.GetCenter().latitude,
              actual_rect.GetCenter().latitude, 1e-10);
  EXPECT_NEAR(expected_rect.GetCenter().longitude,
              actual_rect.GetCenter().longitude, 1e-10);
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, EncodingChecks,
                        ::testing::ValuesIn(GetEncodingDataFromCsv()));

struct ValidityTestData {
  std::string code;
  bool is_valid;
  bool is_short;
  bool is_full;
};

class ValidityChecks : public ::testing::TestWithParam<ValidityTestData> {};

const std::string kValidityTestsFile = "test_data/validityTests.csv";

std::vector<ValidityTestData> GetValidityDataFromCsv() {
  std::vector<ValidityTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kValidityTestsFile);
  for (size_t i = 0; i < csv_records.size(); i++) {
    ValidityTestData test_data = {};
    test_data.code = csv_records[i][0];
    test_data.is_valid = csv_records[i][1] == "true";
    test_data.is_short = csv_records[i][2] == "true";
    test_data.is_full = csv_records[i][3] == "true";
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(ValidityChecks, Validity) {
  ValidityTestData test_data = GetParam();
  EXPECT_EQ(test_data.is_valid, IsValid(test_data.code));
  EXPECT_EQ(test_data.is_full, IsFull(test_data.code));
  EXPECT_EQ(test_data.is_short, IsShort(test_data.code));
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, ValidityChecks,
                        ::testing::ValuesIn(GetValidityDataFromCsv()));

struct ShortCodeTestData {
  std::string full_code;
  double reference_lat;
  double reference_lng;
  std::string short_code;
  std::string test_type;
};

class ShortCodeChecks : public ::testing::TestWithParam<ShortCodeTestData> {};

const std::string kShortCodeTestsFile = "test_data/shortCodeTests.csv";

std::vector<ShortCodeTestData> GetShortCodeDataFromCsv() {
  std::vector<ShortCodeTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kShortCodeTestsFile);
  char *stopstring;
  for (size_t i = 0; i < csv_records.size(); i++) {
    ShortCodeTestData test_data = {};
    test_data.full_code = csv_records[i][0];
    test_data.reference_lat = strtod(csv_records[i][1].c_str(), &stopstring);
    test_data.reference_lng = strtod(csv_records[i][2].c_str(), &stopstring);
    test_data.short_code = csv_records[i][3];
    test_data.test_type = csv_records[i][4];
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(ShortCodeChecks, ShortCode) {
  ShortCodeTestData test_data = GetParam();
  LatLng reference_loc =
      LatLng{test_data.reference_lat, test_data.reference_lng};
  // Shorten the code using the reference location and check.
  if (test_data.test_type == "B" || test_data.test_type == "S") {
    std::string actual_short = Shorten(test_data.full_code, reference_loc);
    EXPECT_EQ(test_data.short_code, actual_short);
  }
  // Now extend the code using the reference location and check.
  if (test_data.test_type == "B" || test_data.test_type == "R") {
    std::string actual_full = RecoverNearest(test_data.short_code, reference_loc);
    EXPECT_EQ(test_data.full_code, actual_full);
  }
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, ShortCodeChecks,
                        ::testing::ValuesIn(GetShortCodeDataFromCsv()));

TEST(MaxCodeLengthChecks, MaxCodeLength) {
  LatLng loc = LatLng{51.3701125, -10.202665625};
  // Check we do not return a code longer than is valid.
  std::string long_code = Encode(loc, 1000000);
  // The code length is the maximum digit count plus one for the separator.
  EXPECT_EQ(long_code.size(), 1 + internal::kMaximumDigitCount);
  EXPECT_TRUE(IsValid(long_code));
  Decode(long_code);
  // Extend the code and make sure it is no longer valid.
  std::string too_long_code = long_code + "W";
  EXPECT_FALSE(IsValid(too_long_code));
  // Ensure too many characters after the separator also causes a fail, even if
  // the total number of characters is ok.
  too_long_code = long_code.substr(6) + "WW";
  EXPECT_TRUE(too_long_code.size() < internal::kMaximumDigitCount);
  EXPECT_FALSE(IsValid(too_long_code));
}

}  // namespace
}  // namespace openlocationcode
<commit_msg>Update openlocationcode_test.cc<commit_after>#include "openlocationcode.h"
#include "codearea.h"

#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>

#include "gtest/gtest.h"

namespace openlocationcode {
namespace internal {
namespace {

TEST(ParameterChecks, PairCodeLengthIsEven) {
  EXPECT_EQ(0, internal::kPairCodeLength % 2);
}

TEST(ParameterChecks, AlphabetIsOrdered) {
  char last = 0;
  for (size_t i = 0; i < internal::kEncodingBase; i++) {
    EXPECT_TRUE(internal::kAlphabet[i] > last);
    last = internal::kAlphabet[i];
  }
}

TEST(ParameterChecks, SeparatorPositionValid) {
  EXPECT_TRUE(internal::kSeparatorPosition <= internal::kPairCodeLength);
}

TEST(ParameterChecks, ShortenDegreesValid) {
  EXPECT_TRUE(internal::kMinShortenDegrees >= internal::kGridSizeDegrees);
}

}  // namespace
}  // namespace internal

namespace {

std::vector<std::vector<std::string>> ParseCsv(std::string path_to_file) {
  std::vector<std::vector<std::string>> csv_records;
  std::string line;

  std::ifstream input_stream(path_to_file, std::ifstream::binary);
  while (std::getline(input_stream, line)) {
    // Ignore comments in the file
    if (line.at(0) == '#') {
      continue;
    }
    std::vector<std::string> line_records;
    std::stringstream lineStream(line);
    std::string cell;
    while (std::getline(lineStream, cell, ',')) {
      line_records.push_back(cell);
    }
    csv_records.push_back(line_records);
  }
  EXPECT_GT(csv_records.size(), 0);
  return csv_records;
}

struct EncodingTestData {
  std::string code;
  double lat_deg;
  double lng_deg;
  double lo_lat_deg;
  double lo_lng_deg;
  double hi_lat_deg;
  double hi_lng_deg;
};

class EncodingChecks : public ::testing::TestWithParam<EncodingTestData> {};

const std::string kEncodingTestsFile = "test_data/encodingTests.csv";

std::vector<EncodingTestData> GetEncodingDataFromCsv() {
  std::vector<EncodingTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kEncodingTestsFile);
  for (size_t i = 0; i < csv_records.size(); i++) {
    EncodingTestData test_data = {};
    test_data.code = csv_records[i][0];
    test_data.lat_deg = strtod(csv_records[i][1].c_str(), nullptr);
    test_data.lng_deg = strtod(csv_records[i][2].c_str(), nullptr);
    test_data.lo_lat_deg = strtod(csv_records[i][3].c_str(), nullptr);
    test_data.lo_lng_deg = strtod(csv_records[i][4].c_str(), nullptr);
    test_data.hi_lat_deg = strtod(csv_records[i][5].c_str(), nullptr);
    test_data.hi_lng_deg = strtod(csv_records[i][6].c_str(), nullptr);
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(EncodingChecks, Encode) {
  EncodingTestData test_data = GetParam();
  CodeArea expected_rect =
      CodeArea(test_data.lo_lat_deg, test_data.lo_lng_deg, test_data.hi_lat_deg,
               test_data.hi_lng_deg, CodeLength(test_data.code));
  LatLng lat_lng = LatLng{test_data.lat_deg, test_data.lng_deg};
  // Encode the test location and make sure we get the expected code.
  std::string actual_code = Encode(lat_lng, CodeLength(test_data.code));
  EXPECT_EQ(test_data.code, actual_code);
  // Now decode the code and check we get the correct coordinates.
  CodeArea actual_rect = Decode(test_data.code);
  EXPECT_NEAR(expected_rect.GetCenter().latitude,
              actual_rect.GetCenter().latitude, 1e-10);
  EXPECT_NEAR(expected_rect.GetCenter().longitude,
              actual_rect.GetCenter().longitude, 1e-10);
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, EncodingChecks,
                        ::testing::ValuesIn(GetEncodingDataFromCsv()));

struct ValidityTestData {
  std::string code;
  bool is_valid;
  bool is_short;
  bool is_full;
};

class ValidityChecks : public ::testing::TestWithParam<ValidityTestData> {};

const std::string kValidityTestsFile = "test_data/validityTests.csv";

std::vector<ValidityTestData> GetValidityDataFromCsv() {
  std::vector<ValidityTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kValidityTestsFile);
  for (size_t i = 0; i < csv_records.size(); i++) {
    ValidityTestData test_data = {};
    test_data.code = csv_records[i][0];
    test_data.is_valid = csv_records[i][1] == "true";
    test_data.is_short = csv_records[i][2] == "true";
    test_data.is_full = csv_records[i][3] == "true";
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(ValidityChecks, Validity) {
  ValidityTestData test_data = GetParam();
  EXPECT_EQ(test_data.is_valid, IsValid(test_data.code));
  EXPECT_EQ(test_data.is_full, IsFull(test_data.code));
  EXPECT_EQ(test_data.is_short, IsShort(test_data.code));
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, ValidityChecks,
                        ::testing::ValuesIn(GetValidityDataFromCsv()));

struct ShortCodeTestData {
  std::string full_code;
  double reference_lat;
  double reference_lng;
  std::string short_code;
  std::string test_type;
};

class ShortCodeChecks : public ::testing::TestWithParam<ShortCodeTestData> {};

const std::string kShortCodeTestsFile = "test_data/shortCodeTests.csv";

std::vector<ShortCodeTestData> GetShortCodeDataFromCsv() {
  std::vector<ShortCodeTestData> data_results;
  std::vector<std::vector<std::string>> csv_records =
      ParseCsv(kShortCodeTestsFile);
  for (size_t i = 0; i < csv_records.size(); i++) {
    ShortCodeTestData test_data = {};
    test_data.full_code = csv_records[i][0];
    test_data.reference_lat = strtod(csv_records[i][1].c_str(), nullptr);
    test_data.reference_lng = strtod(csv_records[i][2].c_str(), nullptr);
    test_data.short_code = csv_records[i][3];
    test_data.test_type = csv_records[i][4];
    data_results.push_back(test_data);
  }
  return data_results;
}

TEST_P(ShortCodeChecks, ShortCode) {
  ShortCodeTestData test_data = GetParam();
  LatLng reference_loc =
      LatLng{test_data.reference_lat, test_data.reference_lng};
  // Shorten the code using the reference location and check.
  if (test_data.test_type == "B" || test_data.test_type == "S") {
    std::string actual_short = Shorten(test_data.full_code, reference_loc);
    EXPECT_EQ(test_data.short_code, actual_short);
  }
  // Now extend the code using the reference location and check.
  if (test_data.test_type == "B" || test_data.test_type == "R") {
    std::string actual_full = RecoverNearest(test_data.short_code, reference_loc);
    EXPECT_EQ(test_data.full_code, actual_full);
  }
}

INSTANTIATE_TEST_CASE_P(OLC_Tests, ShortCodeChecks,
                        ::testing::ValuesIn(GetShortCodeDataFromCsv()));

TEST(MaxCodeLengthChecks, MaxCodeLength) {
  LatLng loc = LatLng{51.3701125, -10.202665625};
  // Check we do not return a code longer than is valid.
  std::string long_code = Encode(loc, 1000000);
  // The code length is the maximum digit count plus one for the separator.
  EXPECT_EQ(long_code.size(), 1 + internal::kMaximumDigitCount);
  EXPECT_TRUE(IsValid(long_code));
  Decode(long_code);
  // Extend the code and make sure it is no longer valid.
  std::string too_long_code = long_code + "W";
  EXPECT_FALSE(IsValid(too_long_code));
  // Ensure too many characters after the separator also causes a fail, even if
  // the total number of characters is ok.
  too_long_code = long_code.substr(6) + "WW";
  EXPECT_TRUE(too_long_code.size() < internal::kMaximumDigitCount);
  EXPECT_FALSE(IsValid(too_long_code));
}

}  // namespace
}  // namespace openlocationcode
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

#if (!defined(_WIN32) && !defined(WIN32))
#include <sys/types.h>
#include <dirent.h>
#endif

#include "BundleMgr.h"
#include "Bundle.h"

Bundle		*BundleMgr::currentBundle	= NULL;

std::string	BundleMgr::bundlePath		= "./data";

BundleMgr::BundleMgr(const std::string &path, const std::string &name)
{
  bundlePath = path;
  bundleName = name;
}

BundleMgr::~BundleMgr()
{
  for (BundleMap::iterator it = bundles.begin(); it != bundles.end(); ++it)
    delete it->second;
  bundles.clear();
}

Bundle *BundleMgr::getBundle(const std::string &locale, bool setcur /*= true*/)
{
  BundleMap::iterator it = bundles.find(locale);
  if (it != bundles.end()) {
    if (setcur) currentBundle = it->second;
    return it->second;
  }

  Bundle *parentBundle = NULL;
  if (locale.length() > 0) {
    std::string parentLocale = locale;

    int underPos = parentLocale.find_last_of('_');
    if (underPos >= 0)
      parentLocale = parentLocale.substr(0,underPos);
    else
      parentLocale.resize(0);
    parentBundle = getBundle(parentLocale);
  }

  Bundle *pB = new Bundle(parentBundle);

  std::string path = bundlePath + "/l10n/" + bundleName;

  if (locale.length() > 0)
    path += "_" + locale;
  path += ".po";

#ifdef __APPLE__
  // This is MacOS X. Use the CoreFoundation resource location API
  // to find the correct language resource if 'default' is specified.
  if (locale.length() == 7 && locale.compare("default") == 0) {
    char	localePath[512];
    CFBundleRef	mainBundle = CFBundleGetMainBundle();
    CFArrayRef	locales	= NULL;
    CFURLRef	localeURL	= NULL;
    // Look for a resource in the main bundle by name and type.
    do {
      if (mainBundle == NULL) break;
      locales = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR("po"), NULL);
      if (locales == NULL || CFArrayGetCount(locales) == 0) break;
      localeURL = (CFURLRef) CFArrayGetValueAtIndex(locales, 0);
      if(localeURL != NULL && ::CFURLGetFileSystemRepresentation(
	  localeURL, true, reinterpret_cast<UInt8 *>(localePath), sizeof(localePath))
	 ) {
	path = localePath;
      }
    } while(0);
    CFRelease(locales);
  }
#endif

  pB->load(path);

  bundles.insert(std::pair<std::string,Bundle*>(locale, pB));

  if (setcur) currentBundle = pB;

  return pB;
}

Bundle *BundleMgr::getCurrentBundle()
{
    return currentBundle;
}

bool BundleMgr::getLocaleList(std::vector<std::string> *list) {
  if (list == NULL) return false;
  // There could have been stuff added to the list
  // prior to this call. Save the list count.
  int 	initSize = list->size();

  do {

#if (defined(_WIN32) || defined(WIN32))
    char fileName[255], *end = NULL;

    // Prepare the wildcarded file path to search for and copy it to fileName
    sprintf(fileName, "%s\\l10n\\bzflag_*.po", bundlePath.c_str());

    HANDLE		hFoundFile	= NULL;
    WIN32_FIND_DATA	data;

    hFoundFile = FindFirstFile((LPCTSTR) fileName, &data);
    if (hFoundFile == INVALID_HANDLE_VALUE) break;	// Invalid path

    do {
      std::string poFile = data.cFileName;
      int dotPos = poFile.find_first_of('.');
      if ((dotPos >= 0) && (poFile.substr(dotPos+1) == "po")) {
	 int underPos = poFile.find_first_of('_');
	 if (underPos >= 0) {
	   std::string locale = poFile.substr(underPos+1, dotPos-underPos-1);
	   if (locale != "xx")
	     list->push_back(locale);
	 }
      }
    } while (FindNextFile(hFoundFile, &data) == TRUE);

    FindClose(hFoundFile);
    break;

#else

    // This should work for most of the currently supported
    // non Windows platforms i believe.
    DIR *localedir = opendir((bundlePath + "/l10n/").c_str());
    if (localedir == NULL) break;
    struct dirent	*dirinfo = NULL;
    while ((dirinfo = readdir(localedir)) != NULL) {

      std::string poFile = dirinfo->d_name;
      int dotPos = poFile.find_first_of('.');
      if ((dotPos >= 0) && (poFile.substr(dotPos+1) == "po")) {
	 int underPos = poFile.find_first_of('_');
	 if (underPos >= 0) {
	   std::string locale = poFile.substr(underPos+1, dotPos-underPos-1);
	   if (locale != "xx")
	     list->push_back(locale);
	 }
      }
    }

    closedir(localedir);

#endif

  } while (0);

  return ((int)list->size() > initSize) ? true : false;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>unused var removed<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

#if (!defined(_WIN32) && !defined(WIN32))
#include <sys/types.h>
#include <dirent.h>
#endif

#include "BundleMgr.h"
#include "Bundle.h"

Bundle		*BundleMgr::currentBundle	= NULL;

std::string	BundleMgr::bundlePath		= "./data";

BundleMgr::BundleMgr(const std::string &path, const std::string &name)
{
  bundlePath = path;
  bundleName = name;
}

BundleMgr::~BundleMgr()
{
  for (BundleMap::iterator it = bundles.begin(); it != bundles.end(); ++it)
    delete it->second;
  bundles.clear();
}

Bundle *BundleMgr::getBundle(const std::string &locale, bool setcur /*= true*/)
{
  BundleMap::iterator it = bundles.find(locale);
  if (it != bundles.end()) {
    if (setcur) currentBundle = it->second;
    return it->second;
  }

  Bundle *parentBundle = NULL;
  if (locale.length() > 0) {
    std::string parentLocale = locale;

    int underPos = parentLocale.find_last_of('_');
    if (underPos >= 0)
      parentLocale = parentLocale.substr(0,underPos);
    else
      parentLocale.resize(0);
    parentBundle = getBundle(parentLocale);
  }

  Bundle *pB = new Bundle(parentBundle);

  std::string path = bundlePath + "/l10n/" + bundleName;

  if (locale.length() > 0)
    path += "_" + locale;
  path += ".po";

#ifdef __APPLE__
  // This is MacOS X. Use the CoreFoundation resource location API
  // to find the correct language resource if 'default' is specified.
  if (locale.length() == 7 && locale.compare("default") == 0) {
    char	localePath[512];
    CFBundleRef	mainBundle = CFBundleGetMainBundle();
    CFArrayRef	locales	= NULL;
    CFURLRef	localeURL	= NULL;
    // Look for a resource in the main bundle by name and type.
    do {
      if (mainBundle == NULL) break;
      locales = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR("po"), NULL);
      if (locales == NULL || CFArrayGetCount(locales) == 0) break;
      localeURL = (CFURLRef) CFArrayGetValueAtIndex(locales, 0);
      if(localeURL != NULL && ::CFURLGetFileSystemRepresentation(
	  localeURL, true, reinterpret_cast<UInt8 *>(localePath), sizeof(localePath))
	 ) {
	path = localePath;
      }
    } while(0);
    CFRelease(locales);
  }
#endif

  pB->load(path);

  bundles.insert(std::pair<std::string,Bundle*>(locale, pB));

  if (setcur) currentBundle = pB;

  return pB;
}

Bundle *BundleMgr::getCurrentBundle()
{
    return currentBundle;
}

bool BundleMgr::getLocaleList(std::vector<std::string> *list) {
  if (list == NULL) return false;
  // There could have been stuff added to the list
  // prior to this call. Save the list count.
  int 	initSize = list->size();

  do {

#if (defined(_WIN32) || defined(WIN32))
    char fileName[255];

    // Prepare the wildcarded file path to search for and copy it to fileName
    sprintf(fileName, "%s\\l10n\\bzflag_*.po", bundlePath.c_str());

    HANDLE		hFoundFile	= NULL;
    WIN32_FIND_DATA	data;

    hFoundFile = FindFirstFile((LPCTSTR) fileName, &data);
    if (hFoundFile == INVALID_HANDLE_VALUE) break;	// Invalid path

    do {
      std::string poFile = data.cFileName;
      int dotPos = poFile.find_first_of('.');
      if ((dotPos >= 0) && (poFile.substr(dotPos+1) == "po")) {
	 int underPos = poFile.find_first_of('_');
	 if (underPos >= 0) {
	   std::string locale = poFile.substr(underPos+1, dotPos-underPos-1);
	   if (locale != "xx")
	     list->push_back(locale);
	 }
      }
    } while (FindNextFile(hFoundFile, &data) == TRUE);

    FindClose(hFoundFile);
    break;

#else

    // This should work for most of the currently supported
    // non Windows platforms i believe.
    DIR *localedir = opendir((bundlePath + "/l10n/").c_str());
    if (localedir == NULL) break;
    struct dirent	*dirinfo = NULL;
    while ((dirinfo = readdir(localedir)) != NULL) {

      std::string poFile = dirinfo->d_name;
      int dotPos = poFile.find_first_of('.');
      if ((dotPos >= 0) && (poFile.substr(dotPos+1) == "po")) {
	 int underPos = poFile.find_first_of('_');
	 if (underPos >= 0) {
	   std::string locale = poFile.substr(underPos+1, dotPos-underPos-1);
	   if (locale != "xx")
	     list->push_back(locale);
	 }
      }
    }

    closedir(localedir);

#endif

  } while (0);

  return ((int)list->size() > initSize) ? true : false;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <cstring>

#include <bmx/ByteArray.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

ByteArray::ByteArray()
{
    mBytes = 0;
    mSize = 0;
    mIsCopy = false;
    mAllocatedSize = 0;
    mAllocBlockSize = 256;
}

ByteArray::ByteArray(uint32_t size)
{
    mBytes = 0;
    mSize = 0;
    mIsCopy = false;
    mAllocatedSize = 0;
    mAllocBlockSize = 256;

    Allocate(size);
}

ByteArray::~ByteArray()
{
    if (!mIsCopy)
        delete [] mBytes;
}

void ByteArray::SetAllocBlockSize(uint32_t block_size)
{
    BMX_CHECK(block_size > 0);
    mAllocBlockSize = block_size;
}

unsigned char* ByteArray::GetBytes() const
{
    return mBytes;
}

uint32_t ByteArray::GetSize() const
{
    return mSize;
}

void ByteArray::Append(const unsigned char *bytes, uint32_t size)
{
    BMX_ASSERT(!mIsCopy);

    if (size == 0)
        return;

    Grow(size);

    memcpy(mBytes + mSize, bytes, size);
    mSize += size;
}

unsigned char* ByteArray::GetBytesAvailable() const
{
    BMX_ASSERT(!mIsCopy);

    if (mSize == mAllocatedSize)
        return 0;

    return mBytes + mSize;
}

uint32_t ByteArray::GetSizeAvailable() const
{
    return mAllocatedSize - mSize;
}

void ByteArray::SetSize(uint32_t size)
{
    if (size > mAllocatedSize)
        BMX_EXCEPTION(("Cannot set byte array size > allocated size"));

    mSize = size;
}

void ByteArray::IncrementSize(uint32_t inc)
{
    if (mSize + inc > mAllocatedSize)
        BMX_EXCEPTION(("Cannot set byte array size > allocated size"));

    mSize += inc;
}

void ByteArray::CopyBytes(const unsigned char *bytes, uint32_t size)
{
    SetSize(0);
    Append(bytes, size);
}

void ByteArray::AssignBytes(unsigned char *bytes, uint32_t size)
{
    Clear();

    mBytes = bytes;
    mSize = size;
    mAllocatedSize = 0;
    mIsCopy = true;
}

void ByteArray::Grow(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mSize + min_size > mAllocatedSize)
        Reallocate(mSize + min_size);
}

void ByteArray::Allocate(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mAllocatedSize >= min_size)
        return;

    uint32_t size = ((min_size / mAllocBlockSize) + 1) * mAllocBlockSize;

    delete [] mBytes;
    mBytes = 0;
    mSize = 0;
    mAllocatedSize = 0;

    mBytes = new unsigned char[size];
    memset(mBytes, 0, size);
    mAllocatedSize = size;
}

void ByteArray::Reallocate(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mAllocatedSize >= min_size)
        return;

    if (mSize == 0) {
        delete [] mBytes;
        mBytes = 0;
    }

    uint32_t size = ((min_size / mAllocBlockSize) + 1) * mAllocBlockSize;

    unsigned char *newBytes = new unsigned char[size];
    if (mSize > 0) {
        memcpy(newBytes, mBytes, mSize);
        delete [] mBytes;
        mBytes = 0;
    }
    mBytes = newBytes;
    mAllocatedSize = size;

    if (size < mSize)
        mSize = size;
}

uint32_t ByteArray::GetAllocatedSize() const
{
    return mAllocatedSize;
}

void ByteArray::Clear()
{
    if (mIsCopy) {
        mBytes = 0;
        mSize = 0;
        mAllocatedSize = 0;
        mIsCopy = false;
    } else {
        delete [] mBytes;
        mBytes = 0;
        mSize = 0;
        mAllocatedSize = 0;
    }
}

<commit_msg>init bytes when reallocating in ByteArray<commit_after>/*
 * Copyright (C) 2010, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <cstring>

#include <bmx/ByteArray.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

ByteArray::ByteArray()
{
    mBytes = 0;
    mSize = 0;
    mIsCopy = false;
    mAllocatedSize = 0;
    mAllocBlockSize = 256;
}

ByteArray::ByteArray(uint32_t size)
{
    mBytes = 0;
    mSize = 0;
    mIsCopy = false;
    mAllocatedSize = 0;
    mAllocBlockSize = 256;

    Allocate(size);
}

ByteArray::~ByteArray()
{
    if (!mIsCopy)
        delete [] mBytes;
}

void ByteArray::SetAllocBlockSize(uint32_t block_size)
{
    BMX_CHECK(block_size > 0);
    mAllocBlockSize = block_size;
}

unsigned char* ByteArray::GetBytes() const
{
    return mBytes;
}

uint32_t ByteArray::GetSize() const
{
    return mSize;
}

void ByteArray::Append(const unsigned char *bytes, uint32_t size)
{
    BMX_ASSERT(!mIsCopy);

    if (size == 0)
        return;

    Grow(size);

    memcpy(mBytes + mSize, bytes, size);
    mSize += size;
}

unsigned char* ByteArray::GetBytesAvailable() const
{
    BMX_ASSERT(!mIsCopy);

    if (mSize == mAllocatedSize)
        return 0;

    return mBytes + mSize;
}

uint32_t ByteArray::GetSizeAvailable() const
{
    return mAllocatedSize - mSize;
}

void ByteArray::SetSize(uint32_t size)
{
    if (size > mAllocatedSize)
        BMX_EXCEPTION(("Cannot set byte array size > allocated size"));

    mSize = size;
}

void ByteArray::IncrementSize(uint32_t inc)
{
    if (mSize + inc > mAllocatedSize)
        BMX_EXCEPTION(("Cannot set byte array size > allocated size"));

    mSize += inc;
}

void ByteArray::CopyBytes(const unsigned char *bytes, uint32_t size)
{
    SetSize(0);
    Append(bytes, size);
}

void ByteArray::AssignBytes(unsigned char *bytes, uint32_t size)
{
    Clear();

    mBytes = bytes;
    mSize = size;
    mAllocatedSize = 0;
    mIsCopy = true;
}

void ByteArray::Grow(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mSize + min_size > mAllocatedSize)
        Reallocate(mSize + min_size);
}

void ByteArray::Allocate(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mAllocatedSize >= min_size)
        return;

    uint32_t size = ((min_size / mAllocBlockSize) + 1) * mAllocBlockSize;

    delete [] mBytes;
    mBytes = 0;
    mSize = 0;
    mAllocatedSize = 0;

    mBytes = new unsigned char[size];
    memset(mBytes, 0, size);
    mAllocatedSize = size;
}

void ByteArray::Reallocate(uint32_t min_size)
{
    BMX_ASSERT(!mIsCopy);

    if (mAllocatedSize >= min_size)
        return;

    if (mSize == 0) {
        delete [] mBytes;
        mBytes = 0;
    }

    uint32_t size = ((min_size / mAllocBlockSize) + 1) * mAllocBlockSize;

    unsigned char *newBytes = new unsigned char[size];
    if (mSize > 0) {
        memcpy(newBytes, mBytes, mSize);
        delete [] mBytes;
        mBytes = 0;
    }
    memset(&newBytes[mSize], 0, size - mSize);
    mBytes = newBytes;
    mAllocatedSize = size;

    if (size < mSize)
        mSize = size;
}

uint32_t ByteArray::GetAllocatedSize() const
{
    return mAllocatedSize;
}

void ByteArray::Clear()
{
    if (mIsCopy) {
        mBytes = 0;
        mSize = 0;
        mAllocatedSize = 0;
        mIsCopy = false;
    } else {
        delete [] mBytes;
        mBytes = 0;
        mSize = 0;
        mAllocatedSize = 0;
    }
}

<|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 "base/basictypes.h"
#include "base/file_path.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "base/string_util.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "net/base/net_util.h"

namespace {

const wchar_t kPlaying[] = L"PLAYING";
const wchar_t kReady[] = L"READY";
const wchar_t kFullScreen[] = L"FULLSCREEN";

}  // namespace

class MediaBrowserTest : public InProcessBrowserTest {
 protected:
  MediaBrowserTest() {
    set_show_window(true);
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitch(switches::kEnableVideoFullscreen);
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_file));
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s=%s",
                                   player_gurl.spec().c_str(),
                                   tag,
                                   media_file);

    ui_test_utils::NavigateToURL(browser(), GURL(url));

    // Allow the media file to be loaded.
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);

    string16 title;
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kPlaying), title);
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }

  void PlayVideoFullScreen(const char* media_file) {
    FilePath test_file;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_file));
    test_file = test_file.AppendASCII("media/player_fullscreen.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s",
                                   player_gurl.spec().c_str(),
                                   media_file);

    ui_test_utils::NavigateToURL(browser(), GURL(url));
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);
    string16 title;
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kReady), title);

    ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kFullScreen), title);
  }
};

// Crashes on Mac OS (http://crbug.com/54939)
#if defined(OS_MACOSX)
#define MAYBE_VideoBearTheora FLAKY_VideoBearTheora
#else
#define MAYBE_VideoBearTheora VideoBearTheora
#endif

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, MAYBE_VideoBearTheora) {
  PlayVideo("bear.ogv");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaBrowserTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaBrowserTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

// TODO(imcheng): Disabled until fullscreen Webkit patch is here - See
// http://crbug.com/54838.
// (Does Mac have fullscreen?)
#if defined(OS_WIN) || defined(OS_LINUX)
IN_PROC_BROWSER_TEST_F(MediaBrowserTest, DISABLED_VideoBearFullScreen) {
  PlayVideoFullScreen("bear.ogv");
}
#endif  // defined(OS_WIN) || defined(OS_LINUX)

TEST_F(UILayoutTest, MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<commit_msg>Revert 58921 - Mark MediaBrowserTest.VideoBearTheora as FLAKY on Mac OS.<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 "base/basictypes.h"
#include "base/file_path.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "base/string_util.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "net/base/net_util.h"

namespace {

const wchar_t kPlaying[] = L"PLAYING";
const wchar_t kReady[] = L"READY";
const wchar_t kFullScreen[] = L"FULLSCREEN";

}  // namespace

class MediaBrowserTest : public InProcessBrowserTest {
 protected:
  MediaBrowserTest() {
    set_show_window(true);
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitch(switches::kEnableVideoFullscreen);
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_file));
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s=%s",
                                   player_gurl.spec().c_str(),
                                   tag,
                                   media_file);

    ui_test_utils::NavigateToURL(browser(), GURL(url));

    // Allow the media file to be loaded.
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);

    string16 title;
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kPlaying), title);
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }

  void PlayVideoFullScreen(const char* media_file) {
    FilePath test_file;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_file));
    test_file = test_file.AppendASCII("media/player_fullscreen.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s",
                                   player_gurl.spec().c_str(),
                                   media_file);

    ui_test_utils::NavigateToURL(browser(), GURL(url));
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);
    string16 title;
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kReady), title);

    ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
    ui_test_utils::WaitForNotification(
        NotificationType::TAB_CONTENTS_TITLE_UPDATED);
    ui_test_utils::GetCurrentTabTitle(browser(), &title);
    EXPECT_EQ(WideToUTF16(kFullScreen), title);
  }
};

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearTheora) {
  PlayVideo("bear.ogv");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

IN_PROC_BROWSER_TEST_F(MediaBrowserTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaBrowserTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaBrowserTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

// TODO(imcheng): Disabled until fullscreen Webkit patch is here - See
// http://crbug.com/54838.
// (Does Mac have fullscreen?)
#if defined(OS_WIN) || defined(OS_LINUX)
IN_PROC_BROWSER_TEST_F(MediaBrowserTest, DISABLED_VideoBearFullScreen) {
  PlayVideoFullScreen("bear.ogv");
}
#endif  // defined(OS_WIN) || defined(OS_LINUX)

TEST_F(UILayoutTest, MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<|endoftext|>