<commit_before>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), SecName);
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(SecName + " too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(SecName + " has an invalid magic");
  return Data.slice(4);
}

static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
                        codeview::TypeTableBuilder &TypeTable) {
  // Start the TPI or IPI stream header.
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Flatten the in memory type table.
  TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
    // FIXME: Hash types.
    TpiBuilder.addTypeRecord(Rec, None);
  });
}

// Merge .debug$T sections into IpiData and TpiData.
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
                        codeview::TypeTableBuilder &TypeTable,
                        codeview::TypeTableBuilder &IDTable) {
  // Visit all .debug$T sections to add them to Builder.
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
    if (Data.empty())
      continue;

    BinaryByteStream Stream(Data, support::little);
    codeview::CVTypeArray Types;
    BinaryStreamReader Reader(Stream);
    SmallVector<TypeIndex, 128> SourceToDest;
    // Follow type servers.  If the same type server is encountered more than
    // once for this instance of `PDBTypeServerHandler` (for example if many
    // object files reference the same TypeServer), the types from the
    // TypeServer will only be visited once.
    pdb::PDBTypeServerHandler Handler;
    Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
    if (auto EC = Reader.readArray(Types, Reader.getLength()))
      fatal(EC, "Reader::readArray failed");
    if (auto Err = codeview::mergeTypeStreams(IDTable, TypeTable, SourceToDest,
                                              &Handler, Types))
      fatal(Err, "codeview::mergeTypeStreams failed");
  }

  // Construct TPI stream contents.
  addTypeInfo(Builder.getTpiBuilder(), TypeTable);

  // Construct IPI stream contents.
  addTypeInfo(Builder.getIpiBuilder(), IDTable);
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugT");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
  if (Data.empty())
    return;

  LazyRandomTypeCollection Types(Data, 100);
  TypeDumpVisitor TDV(Types, &W, false);
  // Use a default implementation that does not follow type servers and instead
  // just dumps the contents of the TypeServer2 record.
  if (auto EC = codeview::visitTypeStream(Types, TDV))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugS");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S");
  if (Data.empty())
    return;

  BinaryByteStream Stream(Data, llvm::support::little);
  CVSymbolArray Symbols;
  BinaryStreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  TypeDatabase TDB(0);
  CVSymbolDumper SymbolDumper(W, TDB, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);

  pdb::PDB_UniqueId uuid{};
  if (DI)
    memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
  InfoBuilder.setGuid(uuid);
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  codeview::TypeTableBuilder TypeTable(BAlloc);
  codeview::TypeTableBuilder IDTable(BAlloc);
  mergeDebugT(Symtab, Builder, TypeTable, IDTable);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<commit_msg>Implement various flavors of type merging.<commit_after>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), SecName);
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(SecName + " too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(SecName + " has an invalid magic");
  return Data.slice(4);
}

static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
                        codeview::TypeTableBuilder &TypeTable) {
  // Start the TPI or IPI stream header.
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Flatten the in memory type table.
  TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
    // FIXME: Hash types.
    TpiBuilder.addTypeRecord(Rec, None);
  });
}

// Merge .debug$T sections into IpiData and TpiData.
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
                        codeview::TypeTableBuilder &TypeTable,
                        codeview::TypeTableBuilder &IDTable) {
  // Visit all .debug$T sections to add them to Builder.
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
    if (Data.empty())
      continue;

    BinaryByteStream Stream(Data, support::little);
    codeview::CVTypeArray Types;
    BinaryStreamReader Reader(Stream);
    SmallVector<TypeIndex, 128> SourceToDest;
    // Follow type servers.  If the same type server is encountered more than
    // once for this instance of `PDBTypeServerHandler` (for example if many
    // object files reference the same TypeServer), the types from the
    // TypeServer will only be visited once.
    pdb::PDBTypeServerHandler Handler;
    Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
    if (auto EC = Reader.readArray(Types, Reader.getLength()))
      fatal(EC, "Reader::readArray failed");
    codeview::LazyRandomTypeCollection TypesAndIds(Types, 100);
    if (auto Err = codeview::mergeTypeAndIdRecords(
            IDTable, TypeTable, SourceToDest, &Handler, TypesAndIds))
      fatal(Err, "codeview::mergeTypeStreams failed");
  }

  // Construct TPI stream contents.
  addTypeInfo(Builder.getTpiBuilder(), TypeTable);

  // Construct IPI stream contents.
  addTypeInfo(Builder.getIpiBuilder(), IDTable);
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugT");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
  if (Data.empty())
    return;

  LazyRandomTypeCollection Types(Data, 100);
  TypeDumpVisitor TDV(Types, &W, false);
  // Use a default implementation that does not follow type servers and instead
  // just dumps the contents of the TypeServer2 record.
  if (auto EC = codeview::visitTypeStream(Types, TDV))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugS");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S");
  if (Data.empty())
    return;

  BinaryByteStream Stream(Data, llvm::support::little);
  CVSymbolArray Symbols;
  BinaryStreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  TypeDatabase TDB(0);
  CVSymbolDumper SymbolDumper(W, TDB, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);

  pdb::PDB_UniqueId uuid{};
  if (DI)
    memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
  InfoBuilder.setGuid(uuid);
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  codeview::TypeTableBuilder TypeTable(BAlloc);
  codeview::TypeTableBuilder IDTable(BAlloc);
  mergeDebugT(Symtab, Builder, TypeTable, IDTable);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<|endoftext|>


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

#include "qmediapluginloader_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>

#include <QtMediaServices/qmediaserviceproviderplugin.h>

QT_BEGIN_NAMESPACE

typedef QMap<QString,QObjectList> ObjectListMap;
Q_GLOBAL_STATIC(ObjectListMap, staticMediaPlugins);

QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity):
    m_iid(iid)
{
    m_location = location + QLatin1String("/");
    load();
}

QStringList QMediaPluginLoader::keys() const
{
    return m_instances.keys();
}

QObject* QMediaPluginLoader::instance(QString const &key)
{
    return m_instances.value(key);
}

QList<QObject*> QMediaPluginLoader::instances(QString const &key)
{
    return m_instances.values(key);
}

//to be used for testing purposes only
void QMediaPluginLoader::setStaticPlugins(const QString &location, const QObjectList& objects)
{
    staticMediaPlugins()->insert(location + QLatin1String("/"), objects);
}

void QMediaPluginLoader::load()
{
    if (!m_instances.isEmpty())
        return;

    if (staticMediaPlugins() && staticMediaPlugins()->contains(m_location)) {
        foreach(QObject *o, staticMediaPlugins()->value(m_location)) {
            if (o != 0 && o->qt_metacast(m_iid) != 0) {
                QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
                if (p != 0) {
                    foreach (QString const &key, p->keys())
                        m_instances.insertMulti(key, o);
                }
            }
        }
    } else {
#ifndef QT_NO_LIBRARY
        QStringList     paths = QCoreApplication::libraryPaths();

        foreach (QString const &path, paths) {
            QString     pluginPathName(path + m_location);
            QDir        pluginDir(pluginPathName);

            if (!pluginDir.exists())
                continue;

            foreach (QString pluginLib, pluginDir.entryList(QDir::Files)) {
                QPluginLoader   loader(pluginPathName + pluginLib);

                QObject *o = loader.instance();
                if (o != 0 && o->qt_metacast(m_iid) != 0) {
                    QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
                    if (p != 0) {
                        foreach (QString const &key, p->keys())
                            m_instances.insertMulti(key, o);
                    }

                    continue;
                } else {
                    qWarning() << "QMediaPluginLoader: Failed to load plugin: " << pluginLib << loader.errorString();
                }
                delete o;
                loader.unload();
            }
        }
#endif
    }
}

QT_END_NAMESPACE

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

#include "qmediapluginloader_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>

#include <QtMediaServices/qmediaserviceproviderplugin.h>

QT_BEGIN_NAMESPACE

typedef QMap<QString,QObjectList> ObjectListMap;
Q_GLOBAL_STATIC(ObjectListMap, staticMediaPlugins);

QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity):
    m_iid(iid)
{
    m_location = location + QLatin1String("/");
    load();
}

QStringList QMediaPluginLoader::keys() const
{
    return m_instances.keys();
}

QObject* QMediaPluginLoader::instance(QString const &key)
{
    return m_instances.value(key);
}

QList<QObject*> QMediaPluginLoader::instances(QString const &key)
{
    return m_instances.values(key);
}

//to be used for testing purposes only
void QMediaPluginLoader::setStaticPlugins(const QString &location, const QObjectList& objects)
{
    staticMediaPlugins()->insert(location + QLatin1String("/"), objects);
}

void QMediaPluginLoader::load()
{
    if (!m_instances.isEmpty())
        return;

    if (staticMediaPlugins() && staticMediaPlugins()->contains(m_location)) {
        foreach(QObject *o, staticMediaPlugins()->value(m_location)) {
            if (o != 0 && o->qt_metacast(m_iid) != 0) {
                QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
                if (p != 0) {
                    foreach (QString const &key, p->keys())
                        m_instances.insertMulti(key, o);
                }
            }
        }
    } else {
#ifndef QT_NO_LIBRARY
        QStringList     paths = QCoreApplication::libraryPaths();

        foreach (QString const &path, paths) {
            QString     pluginPathName(path + m_location);
            QDir        pluginDir(pluginPathName);

            if (!pluginDir.exists())
                continue;

            foreach (const QString &pluginLib, pluginDir.entryList(QDir::Files)) {
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
                if (pluginLib.endsWith(QLatin1String(".debug")))
                    continue;
#endif
                QPluginLoader   loader(pluginPathName + pluginLib);

                QObject *o = loader.instance();
                if (o != 0 && o->qt_metacast(m_iid) != 0) {
                    QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
                    if (p != 0) {
                        foreach (QString const &key, p->keys())
                            m_instances.insertMulti(key, o);
                    }

                    continue;
                } else {
                    qWarning() << "QMediaPluginLoader: Failed to load plugin: " << pluginLib << loader.errorString();
                }
                delete o;
                loader.unload();
            }
        }
#endif
    }
}

QT_END_NAMESPACE

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "remotelinuxruncontrolfactory.h"

#include "remotelinuxdebugsupport.h"
#include "remotelinuxrunconfiguration.h"
#include "remotelinuxruncontrol.h"

#include <debugger/debuggerconstants.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/portlist.h>

using namespace Debugger;
using namespace ProjectExplorer;

namespace RemoteLinux {
namespace Internal {

RemoteLinuxRunControlFactory::RemoteLinuxRunControlFactory(QObject *parent)
    : IRunControlFactory(parent)
{
}

RemoteLinuxRunControlFactory::~RemoteLinuxRunControlFactory()
{
}

bool RemoteLinuxRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const
{
    if (mode != NormalRunMode && mode != DebugRunMode)
        return false;

    const QString idStr = QString::fromLatin1(runConfiguration->id().name());
    if (!runConfiguration->isEnabled()
            || !idStr.startsWith(RemoteLinuxRunConfiguration::Id)) {
        return false;
    }

    const RemoteLinuxRunConfiguration * const remoteRunConfig
        = qobject_cast<RemoteLinuxRunConfiguration *>(runConfiguration);
    if (mode == DebugRunMode)
        return remoteRunConfig->portsUsedByDebuggers() <= remoteRunConfig->freePorts().count();
    return true;
}

RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, RunMode mode)
{
    Q_ASSERT(canRun(runConfig, mode));

    RemoteLinuxRunConfiguration *rc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig);
    Q_ASSERT(rc);
    if (mode == ProjectExplorer::NormalRunMode)
        return new RemoteLinuxRunControl(rc);

    const DebuggerStartParameters params
        = AbstractRemoteLinuxDebugSupport::startParameters(rc);
    DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc);
    if (!runControl)
        return 0;
    RemoteLinuxDebugSupport *debugSupport =
        new RemoteLinuxDebugSupport(rc, runControl->engine());
    connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished()));
    return runControl;
}

QString RemoteLinuxRunControlFactory::displayName() const
{
    return tr("Run on remote Linux device");
}

RunConfigWidget *RemoteLinuxRunControlFactory::createConfigurationWidget(RunConfiguration *config)
{
    Q_UNUSED(config)
    return 0;
}

} // namespace Internal
} // namespace RemoteLinux
<commit_msg>embeddedlinux: let F10/F11 start debugging with break on main<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "remotelinuxruncontrolfactory.h"

#include "remotelinuxdebugsupport.h"
#include "remotelinuxrunconfiguration.h"
#include "remotelinuxruncontrol.h"

#include <debugger/debuggerconstants.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/portlist.h>

using namespace Debugger;
using namespace ProjectExplorer;

namespace RemoteLinux {
namespace Internal {

RemoteLinuxRunControlFactory::RemoteLinuxRunControlFactory(QObject *parent)
    : IRunControlFactory(parent)
{
}

RemoteLinuxRunControlFactory::~RemoteLinuxRunControlFactory()
{
}

bool RemoteLinuxRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const
{
    if (mode != NormalRunMode && mode != DebugRunMode && mode != DebugRunModeWithBreakOnMain)
        return false;

    const QString idStr = QString::fromLatin1(runConfiguration->id().name());
    if (!runConfiguration->isEnabled()
            || !idStr.startsWith(RemoteLinuxRunConfiguration::Id)) {
        return false;
    }

    if (mode == NormalRunMode)
        return true;

    const RemoteLinuxRunConfiguration * const remoteRunConfig
        = qobject_cast<RemoteLinuxRunConfiguration *>(runConfiguration);
    return remoteRunConfig->portsUsedByDebuggers() <= remoteRunConfig->freePorts().count();
}

RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, RunMode mode)
{
    Q_ASSERT(canRun(runConfig, mode));

    RemoteLinuxRunConfiguration *rc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig);
    Q_ASSERT(rc);
    if (mode == ProjectExplorer::NormalRunMode)
        return new RemoteLinuxRunControl(rc);

    const DebuggerStartParameters params
        = AbstractRemoteLinuxDebugSupport::startParameters(rc);
    DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc);
    if (!runControl)
        return 0;
    RemoteLinuxDebugSupport *debugSupport =
        new RemoteLinuxDebugSupport(rc, runControl->engine());
    connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished()));
    return runControl;
}

QString RemoteLinuxRunControlFactory::displayName() const
{
    return tr("Run on remote Linux device");
}

RunConfigWidget *RemoteLinuxRunControlFactory::createConfigurationWidget(RunConfiguration *config)
{
    Q_UNUSED(config)
    return 0;
}

} // namespace Internal
} // namespace RemoteLinux
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010, Willow Garage, Inc.
 * All rights reserved.
 *
 * 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 Willow Garage, Inc. 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.
 */

#include "mesh_resource_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"

#include "rviz/display_context.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreMaterialManager.h>
#include <OgreTextureManager.h>
#include <OgreSharedPtr.h>
#include <OgreTechnique.h>

namespace rviz
{

MeshResourceMarker::MeshResourceMarker(MarkerDisplay* owner, DisplayContext* context, Ogre::SceneNode* parent_node)
: MarkerBase(owner, context, parent_node)
, entity_(0)
{
}

MeshResourceMarker::~MeshResourceMarker()
{
  reset();
}

void MeshResourceMarker::reset()
{
  //destroy entity
  if (entity_)
  {
    context_->getSceneManager()->destroyEntity(entity_);
    entity_ = 0;
  }

  // destroy all the materials we've created
  S_MaterialPtr::iterator it;
  for (it = materials_.begin(); it != materials_.end(); it++)
  {
    Ogre::MaterialPtr material = *it;
    if (!material.isNull())
    {
      material->unload();
      Ogre::MaterialManager::getSingleton().remove(material->getName());
    }
  }
  materials_.clear();
  // the actual passes are deleted by the material
  color_tint_passes_.clear();
}

void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::MESH_RESOURCE);

  // flag indicating if the mesh material color needs to be updated
  bool update_color = false;

  scene_node_->setVisible(false);

  if (!entity_ ||
      old_message->mesh_resource != new_message->mesh_resource ||
      old_message->mesh_use_embedded_materials != new_message->mesh_use_embedded_materials)
  {
    reset();

    if (new_message->mesh_resource.empty())
    {
      return;
    }

    if (loadMeshFromResource(new_message->mesh_resource).isNull())
    {
      std::stringstream ss;
      ss << "Mesh resource marker [" << getStringID() << "] could not load [" << new_message->mesh_resource << "]";
      if (owner_)
      {
        owner_->setMarkerStatus(getID(), StatusProperty::Error, ss.str());
      }
      ROS_DEBUG("%s", ss.str().c_str());
      return;
    }

    static uint32_t count = 0;
    std::stringstream ss;
    ss << "mesh_resource_marker_" << count++;
    std::string id = ss.str();
    entity_ = context_->getSceneManager()->createEntity(id, new_message->mesh_resource);
    scene_node_->attachObject(entity_);

    // create a default material for any sub-entities which don't have their own.
    ss << "Material";
    Ogre::MaterialPtr default_material = Ogre::MaterialManager::getSingleton().create(ss.str(), ROS_PACKAGE_NAME);
    default_material->setReceiveShadows(false);
    default_material->getTechnique(0)->setLightingEnabled(true);
    default_material->getTechnique(0)->setAmbient(0.5, 0.5, 0.5);
    materials_.insert(default_material);

    if (new_message->mesh_use_embedded_materials)
    {
      // make clones of all embedded materials so selection works correctly
      S_MaterialPtr materials = getMaterials();

      S_MaterialPtr::iterator it;
      for (it = materials.begin(); it != materials.end(); it++)
      {
        if ((*it)->getName() != "BaseWhiteNoLighting")
        {
          Ogre::MaterialPtr new_material = (*it)->clone(id + (*it)->getName());
          materials_.insert(new_material);
        }
      }

      // make sub-entities use cloned materials
      for (uint32_t i = 0; i < entity_->getNumSubEntities(); ++i)
      {
        std::string mat_name = entity_->getSubEntity(i)->getMaterialName();
        if (mat_name != "BaseWhiteNoLighting")
        {
          entity_->getSubEntity(i)->setMaterialName(id + mat_name);
        }
        else
        {
          // BaseWhiteNoLighting is the default material Ogre uses
          // when it sees a mesh with no material.  Here we replace
          // that with our default_material which gets colored with
          // new_message->color.
          entity_->getSubEntity(i)->setMaterial(default_material);
        }
      }
    }
    else
    {
      entity_->setMaterial(default_material);
    }

    // add a pass to every material to perform the color tinting
    S_MaterialPtr::iterator material_it;
    for (material_it = materials_.begin(); material_it != materials_.end(); material_it++)
    {
      Ogre::Technique* technique = (*material_it)->getTechnique(0);
      color_tint_passes_.push_back(technique->createPass());
    }

    // always update color on resource change
    update_color = true;

    handler_.reset(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id), context_));
    handler_->addTrackedObject(entity_);
  }
  else
  {
    // underlying mesh resource has not changed but if the color has
    //  then we need to update the materials color
    if (!old_message
        || old_message->color.r != new_message->color.r
        || old_message->color.g != new_message->color.g
        || old_message->color.b != new_message->color.b
        || old_message->color.a != new_message->color.a)
    {
      update_color = true;
    }
  }

  // update material color
  //  if the mesh_use_embedded_materials is true and color is non-zero
  //  then the color will be used to tint the embedded materials
  if (update_color)
  {
    float r = new_message->color.r;
    float g = new_message->color.g;
    float b = new_message->color.b;
    float a = new_message->color.a;

    Ogre::SceneBlendType blending;
    bool depth_write;

    if (a < 0.9998)
    {
      blending = Ogre::SBT_TRANSPARENT_ALPHA;
      depth_write = false;
    }
    else
    {
      blending = Ogre::SBT_REPLACE;
      depth_write = true;
    }

    for (std::vector<Ogre::Pass*>::iterator it = color_tint_passes_.begin();
         it != color_tint_passes_.end();
         ++it)
    {
      (*it)->setAmbient(0.5 * r, 0.5 * g, 0.5 * b);
      (*it)->setDiffuse(r, g, b, a);
      (*it)->setSceneBlending(blending);
      (*it)->setDepthWriteEnabled(depth_write);
      (*it)->setLightingEnabled(true);
    }
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  transform(new_message, pos, orient, scale);

  scene_node_->setVisible(true);
  setPosition(pos);
  setOrientation(orient);

  scene_node_->setScale(scale);
}

S_MaterialPtr MeshResourceMarker::getMaterials()
{
  S_MaterialPtr materials;
  if (entity_)
  {
    extractMaterials(entity_, materials);
  }
  return materials;
}

}

<commit_msg>mesh markers: Fixing mesh alpha and tinting<commit_after>/*
 * Copyright (c) 2010, Willow Garage, Inc.
 * All rights reserved.
 *
 * 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 Willow Garage, Inc. 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.
 */

#include "mesh_resource_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"

#include "rviz/display_context.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreMaterialManager.h>
#include <OgreTextureManager.h>
#include <OgreSharedPtr.h>
#include <OgreTechnique.h>

namespace rviz
{

MeshResourceMarker::MeshResourceMarker(MarkerDisplay* owner, DisplayContext* context, Ogre::SceneNode* parent_node)
: MarkerBase(owner, context, parent_node)
, entity_(0)
{
}

MeshResourceMarker::~MeshResourceMarker()
{
  reset();
}

void MeshResourceMarker::reset()
{
  //destroy entity
  if (entity_)
  {
    context_->getSceneManager()->destroyEntity(entity_);
    entity_ = 0;
  }

  // destroy all the materials we've created
  S_MaterialPtr::iterator it;
  for (it = materials_.begin(); it != materials_.end(); it++)
  {
    Ogre::MaterialPtr material = *it;
    if (!material.isNull())
    {
      material->unload();
      Ogre::MaterialManager::getSingleton().remove(material->getName());
    }
  }
  materials_.clear();
  // the actual passes are deleted by the material
  color_tint_passes_.clear();
}

void MeshResourceMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::MESH_RESOURCE);

  // flag indicating if the mesh material color needs to be updated
  bool update_color = false;

  scene_node_->setVisible(false);

  // Get the color information from the message
  float r = new_message->color.r;
  float g = new_message->color.g;
  float b = new_message->color.b;
  float a = new_message->color.a;

  Ogre::SceneBlendType blending;
  bool depth_write;

  if (a < 0.9998)
  {
    blending = Ogre::SBT_TRANSPARENT_ALPHA;
    depth_write = false;
  }
  else
  {
    blending = Ogre::SBT_REPLACE;
    depth_write = true;
  }

  if (!entity_ ||
      old_message->mesh_resource != new_message->mesh_resource ||
      old_message->mesh_use_embedded_materials != new_message->mesh_use_embedded_materials)
  {
    reset();

    if (new_message->mesh_resource.empty())
    {
      return;
    }

    if (loadMeshFromResource(new_message->mesh_resource).isNull())
    {
      std::stringstream ss;
      ss << "Mesh resource marker [" << getStringID() << "] could not load [" << new_message->mesh_resource << "]";
      if (owner_)
      {
        owner_->setMarkerStatus(getID(), StatusProperty::Error, ss.str());
      }
      ROS_DEBUG("%s", ss.str().c_str());
      return;
    }

    static uint32_t count = 0;
    std::stringstream ss;
    ss << "mesh_resource_marker_" << count++;
    std::string id = ss.str();
    entity_ = context_->getSceneManager()->createEntity(id, new_message->mesh_resource);
    scene_node_->attachObject(entity_);

    // create a default material for any sub-entities which don't have their own.
    ss << "Material";
    Ogre::MaterialPtr default_material = Ogre::MaterialManager::getSingleton().create(ss.str(), ROS_PACKAGE_NAME);
    default_material->setReceiveShadows(false);
    default_material->getTechnique(0)->setLightingEnabled(true);
    default_material->getTechnique(0)->setAmbient(0.5, 0.5, 0.5);

    materials_.insert(default_material);

    if (new_message->mesh_use_embedded_materials)
    {
      // make clones of all embedded materials so selection works correctly
      S_MaterialPtr materials = getMaterials();

      S_MaterialPtr::iterator it;
      for (it = materials.begin(); it != materials.end(); it++)
      {
        if ((*it)->getName() != "BaseWhiteNoLighting")
        {
          Ogre::MaterialPtr new_material = (*it)->clone(id + (*it)->getName());
          materials_.insert(new_material);
        }
      }

      // make sub-entities use cloned materials
      for (uint32_t i = 0; i < entity_->getNumSubEntities(); ++i)
      {
        std::string mat_name = entity_->getSubEntity(i)->getMaterialName();
        if (mat_name != "BaseWhiteNoLighting")
        {
          entity_->getSubEntity(i)->setMaterialName(id + mat_name);
        }
        else
        {
          // BaseWhiteNoLighting is the default material Ogre uses
          // when it sees a mesh with no material.  Here we replace
          // that with our default_material which gets colored with
          // new_message->color.
          entity_->getSubEntity(i)->setMaterial(default_material);
        }
      }
    }
    else
    {
      entity_->setMaterial(default_material);
    }

    // always update color on resource change
    update_color = true;

    handler_.reset(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id), context_));
    handler_->addTrackedObject(entity_);
  }
  else
  {
    // underlying mesh resource has not changed but if the color has
    //  then we need to update the materials color
    if (!old_message
        || old_message->color.r != new_message->color.r
        || old_message->color.g != new_message->color.g
        || old_message->color.b != new_message->color.b
        || old_message->color.a != new_message->color.a)
    {
      update_color = true;
    }
  }

  // update material color
  //  if the mesh_use_embedded_materials is true and color is non-zero
  //  then the color will be used to tint the embedded materials
  if (update_color)
  { // add a pass to every material to perform the color tinting
    S_MaterialPtr::iterator material_it;
    for (material_it = materials_.begin(); material_it != materials_.end(); material_it++)
    {
      Ogre::Technique* technique = (*material_it)->getTechnique(0);

      //color_tint_passes_.push_back(technique->createPass());
      technique->setAmbient( r*0.5, g*0.5, b*0.5 );
      technique->setDiffuse( r, g, b, a );
     technique->setSceneBlending( blending );
     technique->setDepthWriteEnabled( depth_write );
     technique->setLightingEnabled( true );
    }

   // for (std::vector<Ogre::Pass*>::iterator it = color_tint_passes_.begin();
       //  it != color_tint_passes_.end();
        // ++it)
   // {
     //(*it)->setAmbient(0.5 * r, 0.5 * g, 0.5 * b);
     //(*it)->setDiffuse(r, g, b, a);
     //(*it)->setSceneBlending(blending);
    //(*it)->setDepthWriteEnabled(depth_write);
     //(*it)->setLightingEnabled(true);
    //}
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  transform(new_message, pos, orient, scale);

  scene_node_->setVisible(true);
  setPosition(pos);
  setOrientation(orient);

  scene_node_->setScale(scale);
}

S_MaterialPtr MeshResourceMarker::getMaterials()
{
  S_MaterialPtr materials;
  if (entity_)
  {
    extractMaterials(entity_, materials);
  }
  return materials;
}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylanddisplay.h"

#include "qwaylandeventthread.h"
#include "qwaylandwindow.h"
#include "qwaylandscreen.h"
#include "qwaylandcursor.h"
#include "qwaylandinputdevice.h"
#include "qwaylandclipboard.h"
#include "qwaylanddatadevicemanager.h"

#ifdef QT_WAYLAND_GL_SUPPORT
#include "qwaylandglintegration.h"
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#endif

#include "qwaylandextendedoutput.h"
#include "qwaylandextendedsurface.h"
#include "qwaylandsubsurface.h"
#include "qwaylandtouch.h"
#include "qwaylandqtkey.h"

#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>

#include <QtCore/QDebug>

QT_USE_NAMESPACE

struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
    struct wl_surface *surface = mCompositor.create_surface();
    wl_surface_set_user_data(surface, handle);
    return surface;
}

#ifdef QT_WAYLAND_GL_SUPPORT
QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
{
    return mEglIntegration;
}
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration()
{
    return mWindowManagerIntegration;
}
#endif

QWaylandInputDevice *QWaylandDisplay::lastKeyboardFocusInputDevice() const
{
    return mLastKeyboardFocusInputDevice;
}

void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *device)
{
    mLastKeyboardFocusInputDevice = device;
}

static QWaylandDisplay *display = 0;

QWaylandDisplay::QWaylandDisplay()
    : mLastKeyboardFocusInputDevice(0)
    , mDndSelectionHandler(0)
    , mWindowExtension(0)
    , mSubSurfaceExtension(0)
    , mOutputExtension(0)
    , mTouchExtension(0)
    , mQtKeyExtension(0)
{
    display = this;
    qRegisterMetaType<uint32_t>("uint32_t");

    mEventThreadObject = new QWaylandEventThread(0);
    mEventThread = new QThread(this);
    mEventThreadObject->moveToThread(mEventThread);
    mEventThread->start();

    mEventThreadObject->displayConnect();
    mDisplay = mEventThreadObject->display(); //blocks until display is available

    //Create a new even queue for the QtGui thread
    mEventQueue = wl_display_create_queue(mDisplay);

    struct ::wl_registry *registry = wl_display_get_registry(mDisplay);
    wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue);

    init(registry);

    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(flushRequests()));
    connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests()));

#ifdef QT_WAYLAND_GL_SUPPORT
    mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
    mWindowManagerIntegration = new QWaylandWindowManagerIntegration(this);
#endif

    blockingReadEvents();

#ifdef QT_WAYLAND_GL_SUPPORT
    mEglIntegration->initialize();

    flushRequests();
    while (mEglIntegration->waitingForEvents())
        blockingReadEvents();
#endif

    waitForScreens();
}

QWaylandDisplay::~QWaylandDisplay(void)
{
#ifdef QT_WAYLAND_GL_SUPPORT
    delete mEglIntegration;
#endif
    mEventThread->quit();
    mEventThread->wait();
    delete mEventThreadObject;
}

void QWaylandDisplay::flushRequests()
{
    wl_display_dispatch_queue_pending(mDisplay, mEventQueue);
    wl_display_flush(mDisplay);
}

void QWaylandDisplay::blockingReadEvents()
{
    wl_display_dispatch_queue(mDisplay, mEventQueue);
}

QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
{
    for (int i = 0; i < mScreens.size(); ++i) {
        QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
        if (screen->output() == output)
            return screen;
    }
    return 0;
}

void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
{
    Listener l = { listener, data };
    mRegistryListeners.append(l);
}

void QWaylandDisplay::waitForScreens()
{
    flushRequests();
    while (mScreens.isEmpty())
        blockingReadEvents();
}

void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uint32_t version)
{
    Q_UNUSED(version);

    struct ::wl_registry *registry = object();

    if (interface == "wl_output") {
        mScreens.append(new QWaylandScreen(this, id));
    } else if (interface == "wl_compositor") {
        mCompositor.init(registry, id);
    } else if (interface == "wl_shm") {
        mShm = static_cast<struct wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface,1));
    } else if (interface == "wl_shell"){
        mShell = new QtWayland::wl_shell(registry, id);
    } else if (interface == "wl_seat") {
        QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, id);
        mInputDevices.append(inputDevice);
    } else if (interface == "wl_data_device_manager") {
        mDndSelectionHandler = new QWaylandDataDeviceManager(this, id);
    } else if (interface == "wl_output_extension") {
        mOutputExtension = new QtWayland::qt_output_extension(registry, id);
        foreach (QPlatformScreen *screen, screens())
            static_cast<QWaylandScreen *>(screen)->createExtendedOutput();
    } else if (interface == "wl_surface_extension") {
        mWindowExtension = new QtWayland::qt_surface_extension(registry, id);
    } else if (interface == "wl_sub_surface_extension") {
        mSubSurfaceExtension = new QtWayland::qt_sub_surface_extension(registry, id);
    } else if (interface == "wl_touch_extension") {
        mTouchExtension = new QWaylandTouchExtension(this, id);
    } else if (interface == "wl_qtkey_extension") {
        mQtKeyExtension = new QWaylandQtKeyExtension(this, id);
    }

    foreach (Listener l, mRegistryListeners)
        (*l.listener)(l.data, registry, id, interface, version);
}

uint32_t QWaylandDisplay::currentTimeMillisec()
{
    //### we throw away the time information
    struct timeval tv;
    int ret = gettimeofday(&tv, 0);
    if (ret == 0)
        return tv.tv_sec*1000 + tv.tv_usec/1000;
    return 0;
}

void QWaylandDisplay::forceRoundTrip()
{
    wl_display_roundtrip(mDisplay);
}

<commit_msg>Make plugin pick up Qt wayland extensions<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylanddisplay.h"

#include "qwaylandeventthread.h"
#include "qwaylandwindow.h"
#include "qwaylandscreen.h"
#include "qwaylandcursor.h"
#include "qwaylandinputdevice.h"
#include "qwaylandclipboard.h"
#include "qwaylanddatadevicemanager.h"

#ifdef QT_WAYLAND_GL_SUPPORT
#include "qwaylandglintegration.h"
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#endif

#include "qwaylandextendedoutput.h"
#include "qwaylandextendedsurface.h"
#include "qwaylandsubsurface.h"
#include "qwaylandtouch.h"
#include "qwaylandqtkey.h"

#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>

#include <QtCore/QDebug>

QT_USE_NAMESPACE

struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
    struct wl_surface *surface = mCompositor.create_surface();
    wl_surface_set_user_data(surface, handle);
    return surface;
}

#ifdef QT_WAYLAND_GL_SUPPORT
QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
{
    return mEglIntegration;
}
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration()
{
    return mWindowManagerIntegration;
}
#endif

QWaylandInputDevice *QWaylandDisplay::lastKeyboardFocusInputDevice() const
{
    return mLastKeyboardFocusInputDevice;
}

void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *device)
{
    mLastKeyboardFocusInputDevice = device;
}

static QWaylandDisplay *display = 0;

QWaylandDisplay::QWaylandDisplay()
    : mLastKeyboardFocusInputDevice(0)
    , mDndSelectionHandler(0)
    , mWindowExtension(0)
    , mSubSurfaceExtension(0)
    , mOutputExtension(0)
    , mTouchExtension(0)
    , mQtKeyExtension(0)
{
    display = this;
    qRegisterMetaType<uint32_t>("uint32_t");

    mEventThreadObject = new QWaylandEventThread(0);
    mEventThread = new QThread(this);
    mEventThreadObject->moveToThread(mEventThread);
    mEventThread->start();

    mEventThreadObject->displayConnect();
    mDisplay = mEventThreadObject->display(); //blocks until display is available

    //Create a new even queue for the QtGui thread
    mEventQueue = wl_display_create_queue(mDisplay);

    struct ::wl_registry *registry = wl_display_get_registry(mDisplay);
    wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue);

    init(registry);

    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(flushRequests()));
    connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests()));

#ifdef QT_WAYLAND_GL_SUPPORT
    mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
    mWindowManagerIntegration = new QWaylandWindowManagerIntegration(this);
#endif

    blockingReadEvents();

#ifdef QT_WAYLAND_GL_SUPPORT
    mEglIntegration->initialize();

    flushRequests();
    while (mEglIntegration->waitingForEvents())
        blockingReadEvents();
#endif

    waitForScreens();
}

QWaylandDisplay::~QWaylandDisplay(void)
{
#ifdef QT_WAYLAND_GL_SUPPORT
    delete mEglIntegration;
#endif
    mEventThread->quit();
    mEventThread->wait();
    delete mEventThreadObject;
}

void QWaylandDisplay::flushRequests()
{
    wl_display_dispatch_queue_pending(mDisplay, mEventQueue);
    wl_display_flush(mDisplay);
}

void QWaylandDisplay::blockingReadEvents()
{
    wl_display_dispatch_queue(mDisplay, mEventQueue);
}

QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
{
    for (int i = 0; i < mScreens.size(); ++i) {
        QWaylandScreen *screen = static_cast<QWaylandScreen *>(mScreens.at(i));
        if (screen->output() == output)
            return screen;
    }
    return 0;
}

void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
{
    Listener l = { listener, data };
    mRegistryListeners.append(l);
}

void QWaylandDisplay::waitForScreens()
{
    flushRequests();
    while (mScreens.isEmpty())
        blockingReadEvents();
}

void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uint32_t version)
{
    Q_UNUSED(version);

    struct ::wl_registry *registry = object();

    if (interface == "wl_output") {
        mScreens.append(new QWaylandScreen(this, id));
    } else if (interface == "wl_compositor") {
        mCompositor.init(registry, id);
    } else if (interface == "wl_shm") {
        mShm = static_cast<struct wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface,1));
    } else if (interface == "wl_shell"){
        mShell = new QtWayland::wl_shell(registry, id);
    } else if (interface == "wl_seat") {
        QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, id);
        mInputDevices.append(inputDevice);
    } else if (interface == "wl_data_device_manager") {
        mDndSelectionHandler = new QWaylandDataDeviceManager(this, id);
    } else if (interface == "qt_output_extension") {
        mOutputExtension = new QtWayland::qt_output_extension(registry, id);
        foreach (QPlatformScreen *screen, screens())
            static_cast<QWaylandScreen *>(screen)->createExtendedOutput();
    } else if (interface == "qt_surface_extension") {
        mWindowExtension = new QtWayland::qt_surface_extension(registry, id);
    } else if (interface == "qt_sub_surface_extension") {
        mSubSurfaceExtension = new QtWayland::qt_sub_surface_extension(registry, id);
    } else if (interface == "qt_touch_extension") {
        mTouchExtension = new QWaylandTouchExtension(this, id);
    } else if (interface == "qt_qtkey_extension") {
        mQtKeyExtension = new QWaylandQtKeyExtension(this, id);
    }

    foreach (Listener l, mRegistryListeners)
        (*l.listener)(l.data, registry, id, interface, version);
}

uint32_t QWaylandDisplay::currentTimeMillisec()
{
    //### we throw away the time information
    struct timeval tv;
    int ret = gettimeofday(&tv, 0);
    if (ret == 0)
        return tv.tv_sec*1000 + tv.tv_usec/1000;
    return 0;
}

void QWaylandDisplay::forceRoundTrip()
{
    wl_display_roundtrip(mDisplay);
}

<|endoftext|>


<commit_before>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>
#include <IceCandidate.hpp>
#include <webrtcendpoint/kmsicecandidate.h>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 3478;

static std::shared_ptr<std::string> pemCertificate;
std::mutex WebRtcEndpointImpl::certificateMutex;

static void
on_ice_candidate (GstElement *webrtcendpoint, KmsIceCandidate *candidate,
                  gpointer data)
{
  auto handler = reinterpret_cast<std::function<void (KmsIceCandidate *) >*>
                 (data);

  (*handler) (candidate);
}

static void
on_ice_gathering_done (GstElement *webrtcendpoint, gpointer data)
{
  auto handler = reinterpret_cast<std::function<void() >*> (data);

  (*handler) ();
}

class TemporalDirectory
{

public:
  ~TemporalDirectory() {
    if (!dir.string ().empty() ) {
      boost::filesystem::remove_all (dir);
    }
  }

  void setDir (boost::filesystem::path &dir) {
    this->dir = dir;
  }
private:
  boost::filesystem::path dir;
};

static TemporalDirectory tmpDir;

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path temporalDirectory = boost::filesystem::unique_path (
        boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (temporalDirectory);
  tmpDir.setDir (temporalDirectory);

  boost::filesystem::path pemFile = temporalDirectory / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = temporalDirectory / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

std::shared_ptr<std::string>
WebRtcEndpointImpl::getPemCertificate ()
{
  std::unique_lock<std::mutex> lock (certificateMutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      getConfigValue<std::string, WebRtcEndpoint> ("pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    config.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : BaseRtpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  //set properties
  try {
    stunPort = getConfigValue <uint, WebRtcEndpoint> ("stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress = getConfigValue
                    <std::string, WebRtcEndpoint> ("stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Stun address not found in config, cannot operate behind a NAT" );
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = getConfigValue <std::string, WebRtcEndpoint> ("turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate ()->c_str(), NULL);

  onIceCandidateLambda = [&] (KmsIceCandidate * candidate) {
    try {
      std::string cand_str (kms_ice_candidate_get_candidate (candidate) );
      std::string mid_str (kms_ice_candidate_get_sdp_mid (candidate) );
      int sdp_m_line_index = kms_ice_candidate_get_sdp_m_line_index (candidate);
      std::shared_ptr <IceCandidate> cand ( new  IceCandidate
                                            (cand_str, mid_str, sdp_m_line_index) );
      OnIceCandidate event (cand, shared_from_this(), OnIceCandidate::getName() );

      signalOnIceCandidate (event);
    } catch (std::bad_weak_ptr &e) {
    }
  };

  handlerOnIceCandidate = g_signal_connect (element, "on-ice-candidate",
                          G_CALLBACK (on_ice_candidate),
                          &onIceCandidateLambda);

  onIceGatheringDoneLambda = [&] () {
    try {
      OnIceGatheringDone event (shared_from_this(), OnIceGatheringDone::getName() );

      signalOnIceGatheringDone (event);
    } catch (std::bad_weak_ptr &e) {
    }
  };

  handlerOnIceGatheringDone = g_signal_connect (element, "on-ice-gathering-done",
                              G_CALLBACK (on_ice_gathering_done),
                              &onIceGatheringDoneLambda);
}

WebRtcEndpointImpl::~WebRtcEndpointImpl()
{
  g_signal_handler_disconnect (element, handlerOnIceCandidate);
  g_signal_handler_disconnect (element, handlerOnIceGatheringDone);
}

void
WebRtcEndpointImpl::gatherCandidates ()
{
  gboolean ret;

  g_signal_emit_by_name (element, "gather-candidates", &ret);

  if (!ret) {
    throw KurentoException (ICE_GATHER_CANDIDATES_ERROR,
                            "Error gathering candidates");
  }
}

void
WebRtcEndpointImpl::addIceCandidate (std::shared_ptr<IceCandidate> candidate)
{
  gboolean ret;
  const char *cand_str = candidate->getCandidate().c_str ();
  const char *mid_str = candidate->getSdpMid().c_str ();
  guint8 sdp_m_line_index = candidate->getSdpMLineIndex ();
  KmsIceCandidate *cand = kms_ice_candidate_new (cand_str, mid_str,
                          sdp_m_line_index);

  g_signal_emit_by_name (element, "add-ice-candidate", cand, &ret);

  if (!ret) {
    throw KurentoException (ICE_ADD_CANDIDATE_ERROR, "Error adding candidate");
  }
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>WebRtcEndpoint: Fix format<commit_after>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>
#include <IceCandidate.hpp>
#include <webrtcendpoint/kmsicecandidate.h>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 3478;

static std::shared_ptr<std::string> pemCertificate;
std::mutex WebRtcEndpointImpl::certificateMutex;

static void
on_ice_candidate (GstElement *webrtcendpoint, KmsIceCandidate *candidate,
                  gpointer data)
{
  auto handler = reinterpret_cast<std::function<void (KmsIceCandidate *) >*>
                 (data);

  (*handler) (candidate);
}

static void
on_ice_gathering_done (GstElement *webrtcendpoint, gpointer data)
{
  auto handler = reinterpret_cast<std::function<void() >*> (data);

  (*handler) ();
}

class TemporalDirectory
{

public:
  ~TemporalDirectory()
  {
    if (!dir.string ().empty() ) {
      boost::filesystem::remove_all (dir);
    }
  }

  void setDir (boost::filesystem::path &dir)
  {
    this->dir = dir;
  }
private:
  boost::filesystem::path dir;
};

static TemporalDirectory tmpDir;

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path temporalDirectory = boost::filesystem::unique_path (
        boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (temporalDirectory);
  tmpDir.setDir (temporalDirectory);

  boost::filesystem::path pemFile = temporalDirectory / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = temporalDirectory / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

std::shared_ptr<std::string>
WebRtcEndpointImpl::getPemCertificate ()
{
  std::unique_lock<std::mutex> lock (certificateMutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      getConfigValue<std::string, WebRtcEndpoint> ("pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    config.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : BaseRtpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  //set properties
  try {
    stunPort = getConfigValue <uint, WebRtcEndpoint> ("stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress = getConfigValue
                    <std::string, WebRtcEndpoint> ("stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Stun address not found in config, cannot operate behind a NAT" );
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = getConfigValue <std::string, WebRtcEndpoint> ("turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate ()->c_str(), NULL);

  onIceCandidateLambda = [&] (KmsIceCandidate * candidate) {
    try {
      std::string cand_str (kms_ice_candidate_get_candidate (candidate) );
      std::string mid_str (kms_ice_candidate_get_sdp_mid (candidate) );
      int sdp_m_line_index = kms_ice_candidate_get_sdp_m_line_index (candidate);
      std::shared_ptr <IceCandidate> cand ( new  IceCandidate
                                            (cand_str, mid_str, sdp_m_line_index) );
      OnIceCandidate event (cand, shared_from_this(), OnIceCandidate::getName() );

      signalOnIceCandidate (event);
    } catch (std::bad_weak_ptr &e) {
    }
  };

  handlerOnIceCandidate = g_signal_connect (element, "on-ice-candidate",
                          G_CALLBACK (on_ice_candidate),
                          &onIceCandidateLambda);

  onIceGatheringDoneLambda = [&] () {
    try {
      OnIceGatheringDone event (shared_from_this(), OnIceGatheringDone::getName() );

      signalOnIceGatheringDone (event);
    } catch (std::bad_weak_ptr &e) {
    }
  };

  handlerOnIceGatheringDone = g_signal_connect (element, "on-ice-gathering-done",
                              G_CALLBACK (on_ice_gathering_done),
                              &onIceGatheringDoneLambda);
}

WebRtcEndpointImpl::~WebRtcEndpointImpl()
{
  g_signal_handler_disconnect (element, handlerOnIceCandidate);
  g_signal_handler_disconnect (element, handlerOnIceGatheringDone);
}

void
WebRtcEndpointImpl::gatherCandidates ()
{
  gboolean ret;

  g_signal_emit_by_name (element, "gather-candidates", &ret);

  if (!ret) {
    throw KurentoException (ICE_GATHER_CANDIDATES_ERROR,
                            "Error gathering candidates");
  }
}

void
WebRtcEndpointImpl::addIceCandidate (std::shared_ptr<IceCandidate> candidate)
{
  gboolean ret;
  const char *cand_str = candidate->getCandidate().c_str ();
  const char *mid_str = candidate->getSdpMid().c_str ();
  guint8 sdp_m_line_index = candidate->getSdpMLineIndex ();
  KmsIceCandidate *cand = kms_ice_candidate_new (cand_str, mid_str,
                          sdp_m_line_index);

  g_signal_emit_by_name (element, "add-ice-candidate", cand, &ret);

  if (!ret) {
    throw KurentoException (ICE_ADD_CANDIDATE_ERROR, "Error adding candidate");
  }
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>


<commit_before>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <math.h>

#define F(i, a, b) for(int i = a; i <= b; i++)
#define FB(i, a, b) for(int i = a; i >= b; i--)
#define MAX3(a, b, c) (a>b?a:b)>c?(a>b?a:b):c
#define MAXDP 100001
#define maxLen 100001

typedef int entry_type;

using namespace std;

class Queue{
public:
	Queue(){
		begin = 0;
		end = 0;
		length = 0;
		entry_array = new entry_type [maxLen];
	}

	int append( entry_type entry ){
		if( !full() ){
			entry_array[end] = entry;
			if( end <= maxLen-2 ){
				end++;
			}
			else{
				end = 0;
			}
			length++;
			return 0;
		}
		else{
			cerr<<"error: appending: full Queue! can't append anymore!\n";
			return 1;
		}
	}

	int serve(){
		if( !empty() ){
			if( begin <= maxLen-2 ){
				begin++;
			}
			else{
				begin = 0;
			}
			length--;
			return 0;
		}
		else{
			cerr<<"error: serving: empty Queue!\n";
			return 1;
		}
	}

	int retrieve( entry_type *ret ){
		if( !empty() ){
			* ret = entry_array[begin];
			return 0;
		}
		else{
			cerr<<"error: retrieving: empty Queue!\n";
			return 1;
		}
	}

	bool full(){
		if( length >= maxLen ){
			return true;
		}
		else{
			return false;
		}
	}

	bool empty(){
		if( length <= 0 ){
			return true;
		}
		else{
			return false;
		}
	}

	int clear(){
		length = 0;
		begin = 0;
		end = 0;
		return 0;
	}

	int size(){
		return length;
	}

private:
	entry_type * entry_array ;
	int length;
	int begin;
	int end;
};

class Stack{
public:
	Stack(){
		length = 0;
		entry_array = new entry_type [maxLen];
	}

	int push( entry_type entry ){
		if( !full() ){
			entry_array[length] = entry;
			length++;
			return 0;
		}
		else{
			cerr<<"error: pushing: full Stack! can't push anymore!\n";
			return 1;
		}
	}

	int pop(){
		if( !empty() ){
			length--;
			return 0;
		}
		else{
			cerr<<"error: popping: empty Stack!\n";
			return 1;
		}
	}

	int top( entry_type *ret ){
		if( !empty() ){
			* ret = entry_array[length-1];
			return 0;
		}
		else{
			cerr<<"error: topping: empty Stack!\n";
			return 1;
		}
	}

	bool full(){
		if( length >= maxLen ){
			return true;
		}
		else{
			return false;
		}
	}

	bool empty(){
		if( length <= 0 ){
			return true;
		}
		else{
			return false;
		}
	}

	int clear(){
		length = 0;
		return 0;
	}

	int size(){
		return length;
	}

private:
	entry_type * entry_array ;
	int length;
};

int main()
{
	Stack st = Stack();
	int tmp = 0;

	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.pop() ){
		cout << "pop " << endl;
	}
	if( !st.push(3) ){
		cout << "push: " << 3 << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.push(5) ){
		cout << "push: " << 5 << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.clear() ){
		cout << "clear: " << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}

	cout << endl;
	Queue qt = Queue();

	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.serve() ){
		cout << "serve " << endl;
	}
	if( !qt.append(3) ){
		cout << "append: " << 3 << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.append(5) ){
		cout << "append: " << 5 << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.serve() ){
		cout << "serve " << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.clear() ){
		cout << "clear: " << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}

	system("pause");
	return 0;
}

<commit_msg>Update Queue.cpp<commit_after>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <math.h>

#define F(i, a, b) for(int i = a; i <= b; i++)
#define FB(i, a, b) for(int i = a; i >= b; i--)
#define MAX3(a, b, c) (a>b?a:b)>c?(a>b?a:b):c
#define MAXDP 100001
#define maxLen 100001

typedef int entry_type;

using namespace std;

class Queue{
public:
	Queue(){
		begin = 0;
		end = 0;
		length = 0;
		entry_array = new entry_type [maxLen];
	}

	int next(int ret){
		if( ret <= maxLen-2 ){
			ret++;
		}
		else{
			ret = 0;
		}
		return ret;
	}

	int append( entry_type entry ){
		if( !full() ){
			entry_array[end] = entry;
			end = next(end);
			length++;
			return 0;
		}
		else{
			cerr<<"error: appending: full Queue! can't append anymore!\n";
			return 1;
		}
	}

	int serve(){
		if( !empty() ){
			begin = next(begin);
			length--;
			return 0;
		}
		else{
			cerr<<"error: serving: empty Queue!\n";
			return 1;
		}
	}

	int retrieve( entry_type *ret ){
		if( !empty() ){
			* ret = entry_array[begin];
			return 0;
		}
		else{
			cerr<<"error: retrieving: empty Queue!\n";
			return 1;
		}
	}

	bool full(){
		if( length >= maxLen ){
			return true;
		}
		else{
			return false;
		}
	}

	bool empty(){
		if( length <= 0 ){
			return true;
		}
		else{
			return false;
		}
	}

	int clear(){
		length = 0;
		begin = 0;
		end = 0;
		return 0;
	}

	int size(){
		return length;
	}

private:
	entry_type * entry_array ;
	int length;
	int begin;
	int end;
};

class Stack{
public:
	Stack(){
		length = 0;
		entry_array = new entry_type [maxLen];
	}

	int push( entry_type entry ){
		if( !full() ){
			entry_array[length] = entry;
			length++;
			return 0;
		}
		else{
			cerr<<"error: pushing: full Stack! can't push anymore!\n";
			return 1;
		}
	}

	int pop(){
		if( !empty() ){
			length--;
			return 0;
		}
		else{
			cerr<<"error: popping: empty Stack!\n";
			return 1;
		}
	}

	int top( entry_type *ret ){
		if( !empty() ){
			* ret = entry_array[length-1];
			return 0;
		}
		else{
			cerr<<"error: topping: empty Stack!\n";
			return 1;
		}
	}

	bool full(){
		if( length >= maxLen ){
			return true;
		}
		else{
			return false;
		}
	}

	bool empty(){
		if( length <= 0 ){
			return true;
		}
		else{
			return false;
		}
	}

	int clear(){
		length = 0;
		return 0;
	}

	int size(){
		return length;
	}

private:
	entry_type * entry_array ;
	int length;
};

int main()
{
	Stack st = Stack();
	int tmp = 0;

	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.pop() ){
		cout << "pop " << endl;
	}
	if( !st.push(3) ){
		cout << "push: " << 3 << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.push(5) ){
		cout << "push: " << 5 << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}
	if( !st.clear() ){
		cout << "clear: " << endl;
	}
	if( !st.top(&tmp) ){
		cout << "top: " << tmp << endl;
	}

	cout << endl;
	Queue qt = Queue();

	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.serve() ){
		cout << "serve " << endl;
	}
	if( !qt.append(3) ){
		cout << "append: " << 3 << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.append(5) ){
		cout << "append: " << 5 << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.serve() ){
		cout << "serve " << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}
	if( !qt.clear() ){
		cout << "clear: " << endl;
	}
	if( !qt.retrieve(&tmp) ){
		cout << "retrieve: " << tmp << endl;
	}

	system("pause");
	return 0;
}

<|endoftext|>