<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2012 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreVolumeMeshBuilder.h"

#include <limits.h>

#include "OgreHardwareBufferManager.h"
#include "OgreManualObject.h"
#include "OgreMeshManager.h"

namespace Ogre {
namespace Volume {

    bool operator==(Vertex const& a, Vertex const& b)
    {
        return a.x == b.x &&
            a.y == b.y &&
            a.z == b.z &&
            a.nX == b.nX &&
            a.nY == b.nY &&
            a.nZ == b.nZ;
    }

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

    bool operator<(const Vertex& a, const Vertex& b)
    {
         return memcmp(&a, &b, sizeof(Ogre::Volume::Vertex)) < 0;
    }

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

    const unsigned short MeshBuilder::MAIN_BINDING = 0;

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

    MeshBuilder::MeshBuilder(void) : mBoxInit(false)
    {
    }

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

    size_t MeshBuilder::generateBuffers(RenderOperation &operation)
    {
        // Early out if nothing to do.
        if (mIndices.size() == 0)
        {
            return 0;
        }

        // Prepare vertex buffer
        operation.operationType = RenderOperation::OT_TRIANGLE_LIST;

        operation.vertexData = OGRE_NEW VertexData();
        operation.vertexData->vertexCount = mVertices.size();
        operation.vertexData->vertexStart = 0;

        VertexDeclaration *decl = operation.vertexData->vertexDeclaration;
        VertexBufferBinding *bind = operation.vertexData->vertexBufferBinding;

        size_t offset = 0;

        // Add vertex-positions to the buffer
        decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
        offset += VertexElement::getTypeSize(VET_FLOAT3);

        // Add vertex-normals to the buffer
        decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
        offset += VertexElement::getTypeSize(VET_FLOAT3);

        HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
            decl->getVertexSize(MAIN_BINDING),
            operation.vertexData->vertexCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

        bind->setBinding(0, vbuf);

        float* vertices = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));

        VecVertex::const_iterator endVertices = mVertices.end();
        for (VecVertex::const_iterator iter = mVertices.begin(); iter != endVertices; ++iter)
        {
            *vertices++ = (float)iter->x;
            *vertices++ = (float)iter->y;
            *vertices++ = (float)iter->z;
            *vertices++ = (float)iter->nX;
            *vertices++ = (float)iter->nY;
            *vertices++ = (float)iter->nZ;
        }

        vbuf->unlock();

        // Get Indexarray
        operation.indexData = OGRE_NEW IndexData();
        operation.indexData->indexCount = mIndices.size();
        operation.indexData->indexStart = 0;

        VecIndices::const_iterator endIndices = mIndices.end();
        if (operation.indexData->indexCount > USHRT_MAX)
        {
            operation.indexData->indexBuffer =
                HardwareBufferManager::getSingleton().createIndexBuffer(
                HardwareIndexBuffer::IT_32BIT,
                operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

            unsigned int* indices = static_cast<unsigned int*>(
                operation.indexData->indexBuffer->lock(0,
                    operation.indexData->indexBuffer->getSizeInBytes(),
                    HardwareBuffer::HBL_DISCARD));

            for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter)
            {
                *indices++ = *iter;
            }
        }
        else
        {
            operation.indexData->indexBuffer =
                HardwareBufferManager::getSingleton().createIndexBuffer(
                HardwareIndexBuffer::IT_16BIT,
                operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

            unsigned short* indices = static_cast<unsigned short*>(
                operation.indexData->indexBuffer->lock(0,
                    operation.indexData->indexBuffer->getSizeInBytes(),
                    HardwareBuffer::HBL_DISCARD));

            for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter)
            {
                *indices++ = (unsigned short)*iter;
            }
        }

        operation.indexData->indexBuffer->unlock();
        return mIndices.size() / 3;
    }

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

    AxisAlignedBox MeshBuilder::getBoundingBox(void)
    {
        return mBox;
    }

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

    Entity* MeshBuilder::generateWithManualObject(SceneManager *sceneManager, const String &name, const String &material)
    {
            ManualObject* manual = sceneManager->createManualObject();
            manual->begin(material, RenderOperation::OT_TRIANGLE_LIST);

            for (VecVertex::const_iterator iter = mVertices.begin(); iter != mVertices.end(); ++iter)
            {
                manual->position(Vector3(iter->x, iter->y, iter->z));
                manual->normal(Vector3(iter->nX, iter->nY, iter->nZ));
            }
            for (VecIndices::const_iterator iter = mIndices.begin(); iter != mIndices.end(); ++iter)
            {
                manual->index(*iter);
            }

            manual->end();
            StringUtil::StrStreamType meshName;
            meshName << name << "ManualObject";
            MeshManager::getSingleton().remove(meshName.str());
            manual->convertToMesh(meshName.str());
            return sceneManager->createEntity(name, meshName.str());
    }

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

    void MeshBuilder::executeCallback(MeshBuilderCallback *callback) const
    {
        callback->trianglesReady(mVertices, mIndices);
    }

}
}<commit_msg>Volume Rendering: micro cleanup<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2012 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreVolumeMeshBuilder.h"

#include <limits.h>

#include "OgreHardwareBufferManager.h"
#include "OgreManualObject.h"
#include "OgreMeshManager.h"

namespace Ogre {
namespace Volume {

    bool operator==(Vertex const& a, Vertex const& b)
    {
        return a.x == b.x &&
            a.y == b.y &&
            a.z == b.z &&
            a.nX == b.nX &&
            a.nY == b.nY &&
            a.nZ == b.nZ;
    }

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

    bool operator<(const Vertex& a, const Vertex& b)
    {
         return memcmp(&a, &b, sizeof(Vertex)) < 0;
    }

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

    const unsigned short MeshBuilder::MAIN_BINDING = 0;

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

    MeshBuilder::MeshBuilder(void) : mBoxInit(false)
    {
    }

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

    size_t MeshBuilder::generateBuffers(RenderOperation &operation)
    {
        // Early out if nothing to do.
        if (mIndices.size() == 0)
        {
            return 0;
        }

        // Prepare vertex buffer
        operation.operationType = RenderOperation::OT_TRIANGLE_LIST;

        operation.vertexData = OGRE_NEW VertexData();
        operation.vertexData->vertexCount = mVertices.size();
        operation.vertexData->vertexStart = 0;

        VertexDeclaration *decl = operation.vertexData->vertexDeclaration;
        VertexBufferBinding *bind = operation.vertexData->vertexBufferBinding;

        size_t offset = 0;

        // Add vertex-positions to the buffer
        decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
        offset += VertexElement::getTypeSize(VET_FLOAT3);

        // Add vertex-normals to the buffer
        decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
        offset += VertexElement::getTypeSize(VET_FLOAT3);

        HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
            decl->getVertexSize(MAIN_BINDING),
            operation.vertexData->vertexCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

        bind->setBinding(0, vbuf);

        float* vertices = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));

        VecVertex::const_iterator endVertices = mVertices.end();
        for (VecVertex::const_iterator iter = mVertices.begin(); iter != endVertices; ++iter)
        {
            *vertices++ = (float)iter->x;
            *vertices++ = (float)iter->y;
            *vertices++ = (float)iter->z;
            *vertices++ = (float)iter->nX;
            *vertices++ = (float)iter->nY;
            *vertices++ = (float)iter->nZ;
        }

        vbuf->unlock();

        // Get Indexarray
        operation.indexData = OGRE_NEW IndexData();
        operation.indexData->indexCount = mIndices.size();
        operation.indexData->indexStart = 0;

        VecIndices::const_iterator endIndices = mIndices.end();
        if (operation.indexData->indexCount > USHRT_MAX)
        {
            operation.indexData->indexBuffer =
                HardwareBufferManager::getSingleton().createIndexBuffer(
                HardwareIndexBuffer::IT_32BIT,
                operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

            unsigned int* indices = static_cast<unsigned int*>(
                operation.indexData->indexBuffer->lock(0,
                    operation.indexData->indexBuffer->getSizeInBytes(),
                    HardwareBuffer::HBL_DISCARD));

            for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter)
            {
                *indices++ = *iter;
            }
        }
        else
        {
            operation.indexData->indexBuffer =
                HardwareBufferManager::getSingleton().createIndexBuffer(
                HardwareIndexBuffer::IT_16BIT,
                operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

            unsigned short* indices = static_cast<unsigned short*>(
                operation.indexData->indexBuffer->lock(0,
                    operation.indexData->indexBuffer->getSizeInBytes(),
                    HardwareBuffer::HBL_DISCARD));

            for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter)
            {
                *indices++ = (unsigned short)*iter;
            }
        }

        operation.indexData->indexBuffer->unlock();
        return mIndices.size() / 3;
    }

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

    AxisAlignedBox MeshBuilder::getBoundingBox(void)
    {
        return mBox;
    }

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

    Entity* MeshBuilder::generateWithManualObject(SceneManager *sceneManager, const String &name, const String &material)
    {
            ManualObject* manual = sceneManager->createManualObject();
            manual->begin(material, RenderOperation::OT_TRIANGLE_LIST);

            for (VecVertex::const_iterator iter = mVertices.begin(); iter != mVertices.end(); ++iter)
            {
                manual->position(Vector3(iter->x, iter->y, iter->z));
                manual->normal(Vector3(iter->nX, iter->nY, iter->nZ));
            }
            for (VecIndices::const_iterator iter = mIndices.begin(); iter != mIndices.end(); ++iter)
            {
                manual->index(*iter);
            }

            manual->end();
            StringUtil::StrStreamType meshName;
            meshName << name << "ManualObject";
            MeshManager::getSingleton().remove(meshName.str());
            manual->convertToMesh(meshName.str());
            return sceneManager->createEntity(name, meshName.str());
    }

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

    void MeshBuilder::executeCallback(MeshBuilderCallback *callback) const
    {
        callback->trianglesReady(mVertices, mIndices);
    }

}
}<|endoftext|>


<commit_before><commit_msg>cast to pointer to pointer, not just pointer. (confused yet?)<commit_after><|endoftext|>


<commit_before>#include "kerberos_context.h"

Persistent<FunctionTemplate> KerberosContext::constructor_template;

KerberosContext::KerberosContext() : ObjectWrap() {
}

KerberosContext::~KerberosContext() {
}

KerberosContext* KerberosContext::New() {
  NanScope();
  Local<Object> obj = NanNew(constructor_template)->GetFunction()->NewInstance();
  KerberosContext *kerberos_context = ObjectWrap::Unwrap<KerberosContext>(obj);
  return kerberos_context;
}

NAN_METHOD(KerberosContext::New) {
  NanScope();
  // Create code object
  KerberosContext *kerberos_context = new KerberosContext();
  // Wrap it
  kerberos_context->Wrap(args.This());
  // Return the object
  NanReturnValue(args.This());
}

void KerberosContext::Initialize(v8::Handle<v8::Object> target) {
  // Grab the scope of the call from Node
  NanScope();

  // Define a new function template
  // Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
  Local<FunctionTemplate> t = NanNew<v8::FunctionTemplate>(static_cast<NAN_METHOD((*))>(New));
  t->InstanceTemplate()->SetInternalFieldCount(1);
  t->SetClassName(NanNew<String>("KerberosContext"));

  // Get prototype
  Local<ObjectTemplate> proto = t->PrototypeTemplate();

  // Getter for the response
  proto->SetAccessor(NanNew<String>("response"), KerberosContext::ResponseGetter);

  // Getter for the username - server side only
  proto->SetAccessor(NanNew<String>("username"), KerberosContext::UsernameGetter);

  // Getter for the targetname - server side only
  proto->SetAccessor(NanNew<String>("targetname"), KerberosContext::TargetnameGetter);

  // Set persistent
  NanAssignPersistent(constructor_template, t);

  // Set the symbol
  target->ForceSet(NanNew<String>("KerberosContext"), t->GetFunction());
}

// Response Setter / Getter
NAN_GETTER(KerberosContext::ResponseGetter) {
  NanScope();
  gss_client_state *client_state;
  gss_server_state *server_state;

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  // Let's grab the two possible responses
  client_state = context->state;
  server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *response = client_state != NULL ? client_state->response :
	  server_state != NULL ? server_state->response : NULL;

  if(response == NULL) {
    NanReturnValue(NanNull());
  } else {
    // Return the response
    NanReturnValue(NanNew<String>(response));
  }
}

// username Getter
NAN_GETTER(KerberosContext::UsernameGetter) {
  NanScope();

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  gss_client_state *client_state = context->state;
  gss_server_state *server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *username = client_state != NULL ? client_state->username :
	  server_state != NULL ? server_state->username : NULL;

  if(username == NULL) {
    NanReturnValue(NanNull());
  } else {
    NanReturnValue(NanNew<String>(username));
  }
}

// targetname Getter - server side only
NAN_GETTER(KerberosContext::TargetnameGetter) {
  NanScope();

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  gss_server_state *server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *targetname = server_state != NULL ? server_state->targetname : NULL;

  if(targetname == NULL) {
    NanReturnValue(NanNull());
  } else {
    NanReturnValue(NanNew<String>(targetname));
  }
}
<commit_msg>that property is server or client side<commit_after>#include "kerberos_context.h"

Persistent<FunctionTemplate> KerberosContext::constructor_template;

KerberosContext::KerberosContext() : ObjectWrap() {
}

KerberosContext::~KerberosContext() {
}

KerberosContext* KerberosContext::New() {
  NanScope();
  Local<Object> obj = NanNew(constructor_template)->GetFunction()->NewInstance();
  KerberosContext *kerberos_context = ObjectWrap::Unwrap<KerberosContext>(obj);
  return kerberos_context;
}

NAN_METHOD(KerberosContext::New) {
  NanScope();
  // Create code object
  KerberosContext *kerberos_context = new KerberosContext();
  // Wrap it
  kerberos_context->Wrap(args.This());
  // Return the object
  NanReturnValue(args.This());
}

void KerberosContext::Initialize(v8::Handle<v8::Object> target) {
  // Grab the scope of the call from Node
  NanScope();

  // Define a new function template
  // Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
  Local<FunctionTemplate> t = NanNew<v8::FunctionTemplate>(static_cast<NAN_METHOD((*))>(New));
  t->InstanceTemplate()->SetInternalFieldCount(1);
  t->SetClassName(NanNew<String>("KerberosContext"));

  // Get prototype
  Local<ObjectTemplate> proto = t->PrototypeTemplate();

  // Getter for the response
  proto->SetAccessor(NanNew<String>("response"), KerberosContext::ResponseGetter);

  // Getter for the username
  proto->SetAccessor(NanNew<String>("username"), KerberosContext::UsernameGetter);

  // Getter for the targetname - server side only
  proto->SetAccessor(NanNew<String>("targetname"), KerberosContext::TargetnameGetter);

  // Set persistent
  NanAssignPersistent(constructor_template, t);

  // Set the symbol
  target->ForceSet(NanNew<String>("KerberosContext"), t->GetFunction());
}

// Response Setter / Getter
NAN_GETTER(KerberosContext::ResponseGetter) {
  NanScope();
  gss_client_state *client_state;
  gss_server_state *server_state;

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  // Let's grab the two possible responses
  client_state = context->state;
  server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *response = client_state != NULL ? client_state->response :
	  server_state != NULL ? server_state->response : NULL;

  if(response == NULL) {
    NanReturnValue(NanNull());
  } else {
    // Return the response
    NanReturnValue(NanNew<String>(response));
  }
}

// username Getter
NAN_GETTER(KerberosContext::UsernameGetter) {
  NanScope();

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  gss_client_state *client_state = context->state;
  gss_server_state *server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *username = client_state != NULL ? client_state->username :
	  server_state != NULL ? server_state->username : NULL;

  if(username == NULL) {
    NanReturnValue(NanNull());
  } else {
    NanReturnValue(NanNew<String>(username));
  }
}

// targetname Getter - server side only
NAN_GETTER(KerberosContext::TargetnameGetter) {
  NanScope();

  // Unpack the object
  KerberosContext *context = ObjectWrap::Unwrap<KerberosContext>(args.This());

  gss_server_state *server_state = context->server_state;

  // the non-NULL provides a response string, which could be NULL, otherwise NULL.
  char *targetname = server_state != NULL ? server_state->targetname : NULL;

  if(targetname == NULL) {
    NanReturnValue(NanNull());
  } else {
    NanReturnValue(NanNew<String>(targetname));
  }
}
<|endoftext|>


<commit_before>#include "androidretracer.h"

#include "androiddevicedialog.h"

#include "thumbnail.h"

#include "image/image.hpp"
#include "trace_profiler.hpp"

#include <QHostAddress>
#include <QJsonDocument>
#include <QSettings>
#include <QTime>

typedef QLatin1String _;

static QLatin1String packageName("apitrace.github.io.eglretrace");
static QLatin1String activityName("/.RetraceActivity");

AndroidRetracer::AndroidRetracer(QObject *parent)
    : Retracer(parent),
      m_stdoutPort(52341),
      m_stderrPort(52342)
{
    connect(&m_androidUtils, SIGNAL(statusMessage(QString)),
            SIGNAL(statusMessage(QString)));
}

void AndroidRetracer::setAndroidFileName(const QString &fileName)
{
    m_androdiFileName = fileName;
}

static int extractPidFromChunk(const QByteArray &chunk, int from)
{
    int pos1 = chunk.indexOf(' ', from);
    if (pos1 == -1)
        return -1;
    while (chunk[pos1] == ' ')
        ++pos1;
    int pos3 = chunk.indexOf(' ', pos1);
    int pid = chunk.mid(pos1, pos3 - pos1).toInt();
    return pid;
}

static int extractPid(const QByteArray &psOutput)
{
    static const QByteArray needle("apitrace.github.io.eglretrace\r");
    const int to = psOutput.indexOf(needle);
    if (to == -1)
        return -1;
    const int from = psOutput.lastIndexOf('\n', to);
    if (from == -1)
        return -1;
    return extractPidFromChunk(psOutput, from);
}

static QByteArray readLine(QTcpSocket &sock)
{
    while (!sock.canReadLine() && sock.waitForReadyRead());
    if (sock.state() != QAbstractSocket::ConnectedState)
        return QByteArray();
    return sock.readLine();
}

static bool read(QTcpSocket &sock, char *ptr, qint64 sz)
{
    do {
        qint64 readBytes = sock.read(ptr, sz);
        ptr += readBytes;
        sz -= readBytes;
    } while(sz && sock.waitForReadyRead());
    return sz == 0;
}

void AndroidRetracer::run()
{
    m_androidUtils.reloadAdb();
    QString errorStr;
    bool setupRet;
    QMetaObject::invokeMethod(this, "setup", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(bool, setupRet),
                              Q_ARG(QString *, &errorStr));

    if (!setupRet) {
        emit finished(errorStr);
        return;
    }

    if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("am") << _("start") << _("-n") << packageName + activityName)) {
        emit finished(tr("Can't start apitrace application"));
        return;
    }
    QByteArray which;
    if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("readlink") << _("$(which ps)") , &which)) {
        emit finished(tr("Can't start adb"));
        return;
    }

    bool isBusyBox = which.startsWith("busybox");
    QStringList psArgs;
    psArgs << _("shell") << _("ps");
    if (isBusyBox)
        psArgs << _("-w");

    qint64 processPID;
    bool wasStarted = false;
    QTime startTime;
    startTime.start();

    QTcpSocket stdoutSocket;
    QTcpSocket stderrSocket;

    ImageHash thumbnails;

    QVariantMap parsedJson;
    trace::Profile* profile = isProfiling() ? new trace::Profile() : NULL;

    QList<ApiTraceError> errors;
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");

    QString msg = QLatin1String("Replay finished!");
    QByteArray jsonBuffer;
    QByteArray outputBuffer;
    bool keepGoing = true;
    while(keepGoing) {
        if (!wasStarted || startTime.elapsed() > 1000) {
            QByteArray psOut;
            m_androidUtils.runAdb(psArgs, &psOut);
            processPID = extractPid(psOut);
            if (wasStarted)
                startTime.restart();
        }

        if (processPID == -1) {
            if (wasStarted) {
                break;
            } else {
                if (startTime.elapsed() > 3000) { // wait 3 seconds to start
                    emit finished(tr("Unable to start retrace on device."));
                    return;
                }
            }
            msleep(100);
            continue;
        }

        // we have a valid pid, it means the application started
        if (!wasStarted) {
            // connect the sockets
            int tries = 0;
            do {
                stdoutSocket.connectToHost(QHostAddress::LocalHost, m_stdoutPort);
            } while (!stdoutSocket.waitForConnected(100) && ++tries < 10);
            if (stdoutSocket.state() != QAbstractSocket::ConnectedState) {
                emit finished(tr("Can't connect to stdout socket."));
                return;
            }

            // Android doesn't suport GPU and PPD profiling (at leats not on my devices)
            //setProfiling(false, isProfilingCpu(), false);

            QString args = (retraceArguments() << m_androdiFileName).join(" ") + _("\n");
            stdoutSocket.write(args.toUtf8());
            if (!stdoutSocket.waitForBytesWritten()) {
                emit finished(tr("Can't send params."));
                return;
            }

            stderrSocket.connectToHost(QHostAddress::LocalHost, m_stderrPort);
            stderrSocket.waitForConnected(100);
            if (stderrSocket.state() != QAbstractSocket::ConnectedState) {
                emit finished(tr("Can't connect to stderr socket."));
                return;
            }
            wasStarted = true;
        }

        // We are going to read both channels at the same time

        // read stdout channel
        if (stdoutSocket.waitForReadyRead(100)) {
            if (captureState())
                jsonBuffer.append(stdoutSocket.readAll());
            else if (captureThumbnails()) {
                // read one image
                image::PNMInfo info;
                QByteArray header;
                int headerLines = 3; // assume no optional comment line
                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    QByteArray line = readLine(stdoutSocket);
                    if (line.isEmpty()) {
                        keepGoing = false;
                        break;
                    }
                    header += line;
                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && line[0] == '#') {
                        ++headerLines;
                    }
                }

                const char *headerEnd = image::readPNMHeader(header.constData(), header.size(), info);

                // if invalid PNM header was encountered, ...
                if (headerEnd == NULL ||
                    info.channelType != image::TYPE_UNORM8) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    keepGoing = false;
                    break;
                }

                unsigned channels = info.channels;
                unsigned width = info.width;
                unsigned height = info.height;

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    if (!read(stdoutSocket, (char *) scanLine, rowBytes)) {
                        keepGoing = false;
                        break;
                    }
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.insert(info.commentNumber, thumb);
            } else if (isProfiling()) {
                QByteArray line = readLine(stdoutSocket);
                if (line.isEmpty()) {
                    keepGoing = false;
                    break;
                }
                line.append('\0');
                trace::Profiler::parseLine(line.constData(), profile);
            } else {
                outputBuffer.append(stdoutSocket.readAll());
            }
        }

        // read stderr channel
        if (stderrSocket.waitForReadyRead(5) && stderrSocket.canReadLine()) {
            QString line = stderrSocket.readLine();
            if (regexp.indexIn(line) != -1) {
                ApiTraceError error;
                error.callIndex = regexp.cap(1).toInt();
                error.type = regexp.cap(2);
                error.message = regexp.cap(3);
                errors.append(error);
            } else if (!errors.isEmpty()) {
                // Probably a multiligne message
                ApiTraceError &previous = errors.last();
                if (line.endsWith("\n")) {
                    line.chop(1);
                }
                previous.message.append('\n');
                previous.message.append(line);
            }
        }
    }

    if (outputBuffer.size() < 80)
        msg = outputBuffer;

    if (captureState()) {
        QJsonParseError error;
        QJsonDocument jsonDoc =
            QJsonDocument::fromJson(jsonBuffer, &error);

        if (error.error != QJsonParseError::NoError)
            msg = error.errorString();

        parsedJson = jsonDoc.toVariant().toMap();
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
    }

    if (captureThumbnails() && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (isProfiling() && profile) {
        emit foundProfile(profile);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

bool AndroidRetracer::setup(QString *error)
{
    m_androidUtils.reloadAdb();
    if (m_androidUtils.serialNumber().isEmpty()) {
        *error = tr("No device selected");
        return false;
    }

    // forward adbPorts
    QSettings s;
    s.beginGroup(_("android"));
    m_stdoutPort = s.value(_("stdoutPort"), m_stdoutPort).toInt();
    m_stderrPort = s.value(_("stderrPort"), m_stderrPort).toInt();
    s.endGroup();

    if (!m_androidUtils.runAdb(QStringList(_("forward"))
              << QString::fromLatin1("tcp:%1").arg(m_stdoutPort)
              << _("localabstract:apitrace.github.io.eglretrace.stdout"))) {
        *error = tr("Can't forward ports");
        return false;
    }

    if (!m_androidUtils.runAdb(QStringList(_("forward"))
              << QString::fromLatin1("tcp:%1").arg(m_stderrPort)
              << _("localabstract:apitrace.github.io.eglretrace.stderr"))) {
        *error = tr("Can't forward ports");
        return false;
    }

    return true;
}
<commit_msg>gui: Try to un-break android retracer.<commit_after>#include "androidretracer.h"

#include "androiddevicedialog.h"

#include "thumbnail.h"

#include "image/image.hpp"
#include "trace_profiler.hpp"

#include <QHostAddress>
#include <QSettings>
#include <QTime>
#include <QBuffer>

#include "qubjson.h"

typedef QLatin1String _;

static QLatin1String packageName("apitrace.github.io.eglretrace");
static QLatin1String activityName("/.RetraceActivity");

AndroidRetracer::AndroidRetracer(QObject *parent)
    : Retracer(parent),
      m_stdoutPort(52341),
      m_stderrPort(52342)
{
    connect(&m_androidUtils, SIGNAL(statusMessage(QString)),
            SIGNAL(statusMessage(QString)));
}

void AndroidRetracer::setAndroidFileName(const QString &fileName)
{
    m_androdiFileName = fileName;
}

static int extractPidFromChunk(const QByteArray &chunk, int from)
{
    int pos1 = chunk.indexOf(' ', from);
    if (pos1 == -1)
        return -1;
    while (chunk[pos1] == ' ')
        ++pos1;
    int pos3 = chunk.indexOf(' ', pos1);
    int pid = chunk.mid(pos1, pos3 - pos1).toInt();
    return pid;
}

static int extractPid(const QByteArray &psOutput)
{
    static const QByteArray needle("apitrace.github.io.eglretrace\r");
    const int to = psOutput.indexOf(needle);
    if (to == -1)
        return -1;
    const int from = psOutput.lastIndexOf('\n', to);
    if (from == -1)
        return -1;
    return extractPidFromChunk(psOutput, from);
}

static QByteArray readLine(QTcpSocket &sock)
{
    while (!sock.canReadLine() && sock.waitForReadyRead());
    if (sock.state() != QAbstractSocket::ConnectedState)
        return QByteArray();
    return sock.readLine();
}

static bool read(QTcpSocket &sock, char *ptr, qint64 sz)
{
    do {
        qint64 readBytes = sock.read(ptr, sz);
        ptr += readBytes;
        sz -= readBytes;
    } while(sz && sock.waitForReadyRead());
    return sz == 0;
}

void AndroidRetracer::run()
{
    m_androidUtils.reloadAdb();
    QString errorStr;
    bool setupRet;
    QMetaObject::invokeMethod(this, "setup", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(bool, setupRet),
                              Q_ARG(QString *, &errorStr));

    if (!setupRet) {
        emit finished(errorStr);
        return;
    }

    if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("am") << _("start") << _("-n") << packageName + activityName)) {
        emit finished(tr("Can't start apitrace application"));
        return;
    }
    QByteArray which;
    if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("readlink") << _("$(which ps)") , &which)) {
        emit finished(tr("Can't start adb"));
        return;
    }

    bool isBusyBox = which.startsWith("busybox");
    QStringList psArgs;
    psArgs << _("shell") << _("ps");
    if (isBusyBox)
        psArgs << _("-w");

    qint64 processPID;
    bool wasStarted = false;
    QTime startTime;
    startTime.start();

    QTcpSocket stdoutSocket;
    QTcpSocket stderrSocket;

    ImageHash thumbnails;

    QVariantMap parsedJson;
    trace::Profile* profile = isProfiling() ? new trace::Profile() : NULL;

    QList<ApiTraceError> errors;
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");

    QString msg = QLatin1String("Replay finished!");
    QByteArray ubjsonBuffer;
    QByteArray outputBuffer;
    bool keepGoing = true;
    while(keepGoing) {
        if (!wasStarted || startTime.elapsed() > 1000) {
            QByteArray psOut;
            m_androidUtils.runAdb(psArgs, &psOut);
            processPID = extractPid(psOut);
            if (wasStarted)
                startTime.restart();
        }

        if (processPID == -1) {
            if (wasStarted) {
                break;
            } else {
                if (startTime.elapsed() > 3000) { // wait 3 seconds to start
                    emit finished(tr("Unable to start retrace on device."));
                    return;
                }
            }
            msleep(100);
            continue;
        }

        // we have a valid pid, it means the application started
        if (!wasStarted) {
            // connect the sockets
            int tries = 0;
            do {
                stdoutSocket.connectToHost(QHostAddress::LocalHost, m_stdoutPort);
            } while (!stdoutSocket.waitForConnected(100) && ++tries < 10);
            if (stdoutSocket.state() != QAbstractSocket::ConnectedState) {
                emit finished(tr("Can't connect to stdout socket."));
                return;
            }

            // Android doesn't suport GPU and PPD profiling (at leats not on my devices)
            //setProfiling(false, isProfilingCpu(), false);

            QString args = (retraceArguments() << m_androdiFileName).join(" ") + _("\n");
            stdoutSocket.write(args.toUtf8());
            if (!stdoutSocket.waitForBytesWritten()) {
                emit finished(tr("Can't send params."));
                return;
            }

            stderrSocket.connectToHost(QHostAddress::LocalHost, m_stderrPort);
            stderrSocket.waitForConnected(100);
            if (stderrSocket.state() != QAbstractSocket::ConnectedState) {
                emit finished(tr("Can't connect to stderr socket."));
                return;
            }
            wasStarted = true;
        }

        // We are going to read both channels at the same time

        // read stdout channel
        if (stdoutSocket.waitForReadyRead(100)) {
            if (captureState())
                ubjsonBuffer.append(stdoutSocket.readAll());
            else if (captureThumbnails()) {
                // read one image
                image::PNMInfo info;
                QByteArray header;
                int headerLines = 3; // assume no optional comment line
                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    QByteArray line = readLine(stdoutSocket);
                    if (line.isEmpty()) {
                        keepGoing = false;
                        break;
                    }
                    header += line;
                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && line[0] == '#') {
                        ++headerLines;
                    }
                }

                const char *headerEnd = image::readPNMHeader(header.constData(), header.size(), info);

                // if invalid PNM header was encountered, ...
                if (headerEnd == NULL ||
                    info.channelType != image::TYPE_UNORM8) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    keepGoing = false;
                    break;
                }

                unsigned channels = info.channels;
                unsigned width = info.width;
                unsigned height = info.height;

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    if (!read(stdoutSocket, (char *) scanLine, rowBytes)) {
                        keepGoing = false;
                        break;
                    }
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.insert(info.commentNumber, thumb);
            } else if (isProfiling()) {
                QByteArray line = readLine(stdoutSocket);
                if (line.isEmpty()) {
                    keepGoing = false;
                    break;
                }
                line.append('\0');
                trace::Profiler::parseLine(line.constData(), profile);
            } else {
                outputBuffer.append(stdoutSocket.readAll());
            }
        }

        // read stderr channel
        if (stderrSocket.waitForReadyRead(5) && stderrSocket.canReadLine()) {
            QString line = stderrSocket.readLine();
            if (regexp.indexIn(line) != -1) {
                ApiTraceError error;
                error.callIndex = regexp.cap(1).toInt();
                error.type = regexp.cap(2);
                error.message = regexp.cap(3);
                errors.append(error);
            } else if (!errors.isEmpty()) {
                // Probably a multiligne message
                ApiTraceError &previous = errors.last();
                if (line.endsWith("\n")) {
                    line.chop(1);
                }
                previous.message.append('\n');
                previous.message.append(line);
            }
        }
    }

    if (outputBuffer.size() < 80)
        msg = outputBuffer;

    if (captureState()) {
        QBuffer io(&ubjsonBuffer);
        io.open(QIODevice::ReadOnly);

        parsedJson = decodeUBJSONObject(&io).toMap();
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
    }

    if (captureThumbnails() && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (isProfiling() && profile) {
        emit foundProfile(profile);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

bool AndroidRetracer::setup(QString *error)
{
    m_androidUtils.reloadAdb();
    if (m_androidUtils.serialNumber().isEmpty()) {
        *error = tr("No device selected");
        return false;
    }

    // forward adbPorts
    QSettings s;
    s.beginGroup(_("android"));
    m_stdoutPort = s.value(_("stdoutPort"), m_stdoutPort).toInt();
    m_stderrPort = s.value(_("stderrPort"), m_stderrPort).toInt();
    s.endGroup();

    if (!m_androidUtils.runAdb(QStringList(_("forward"))
              << QString::fromLatin1("tcp:%1").arg(m_stdoutPort)
              << _("localabstract:apitrace.github.io.eglretrace.stdout"))) {
        *error = tr("Can't forward ports");
        return false;
    }

    if (!m_androidUtils.runAdb(QStringList(_("forward"))
              << QString::fromLatin1("tcp:%1").arg(m_stderrPort)
              << _("localabstract:apitrace.github.io.eglretrace.stderr"))) {
        *error = tr("Can't forward ports");
        return false;
    }

    return true;
}
<|endoftext|>


<commit_before>/*
 * $Id: XMReceiverMediaPatch.cpp,v 1.30 2007/02/13 12:57:52 hfriederich Exp $
 *
 * Copyright (c) 2005-2007 XMeeting Project ("http://xmeeting.sf.net").
 * All rights reserved.
 * Copyright (c) 2005-2007 Hannes Friederich. All rights reserved.
 */

#include "XMReceiverMediaPatch.h"

#include <opal/mediastrm.h>
#include <opal/mediacmd.h>

#include "XMMediaFormats.h"
#include "XMMediaStream.h"
#include "XMCallbackBridge.h"

#include "XMAudioTester.h"

#define XM_PACKET_POOL_GRANULARITY 8
#define XM_FRAME_BUFFER_SIZE 352*288*4

XMReceiverMediaPatch::XMReceiverMediaPatch(OpalMediaStream & src)
: OpalMediaPatch(src)
{
	packetReassembler = NULL;
}

XMReceiverMediaPatch::~XMReceiverMediaPatch()
{
}

void XMReceiverMediaPatch::Start()
{
	// quit any running audio test if needed
	XMAudioTester::Stop();

	OpalMediaPatch::Start();
}

void XMReceiverMediaPatch::Main()
{
	///////////////////////////////////////////////////////////////////////////////////////////////
	// The receiving algorithm tries to achieve best-possible data integrity and builds upon
	// the following assumptions:
	//
	// 1) The chance for packets actually being lost/dropped is very small
	// 2) The chance of packets being delayed across timestamp boundaries is much smaller than
	//    the chance of packets being reordered within the same timestamp (the same video frame)
	//
	// First, the frames will be read and put into a sorted linked list with ascending sequence
	// numbers. If a packet group is complete, the packet payloads are copied together and the
	// resulting frame is sent to the XMMediaReceiver class for decompression and display.
	// A packet group is considered to be complete IF
	//
	// a) The first packet has the next ascending sequence number to the sequence number of the
	//    last packet of the previous packet group or the packet contains the beginning of a
	//    coded frame (picture start codes in H.261 / H.263) AND
	// b) The sequence numbers of the packets in the list are ascending with no sequence number
	//    missing AND
	// c) The last packet has the marker bit set
	//
	// This algorithm makes it possible to process packets of a packet group even if they arrive
	// after the last packet of the packet group with the marker bit set. This works well if
	// assumptions 1) and 2) are true.
	//
	// If a packet group is incomplete and the first packet of the next packet group arrives
	// (indicated by a different timestamp), the incomplete packet group is either dropped
	// or processed, depending on the codec being used. If the incomplete packet group is
	// processed, the processing happens delayed since the first packet of the next packet
	// group arrived, leading to inconstant display intervals. As long as assumption 1)
	// is met, this is not a big drawback.
	//
	// If either packets are missing or the decompression of the frame fails, an
	// fast update request is being sent to the remote party.
	///////////////////////////////////////////////////////////////////////////////////////////////

	// Allocating a pool of XMRTPPacket instances to reduce
	// buffer allocation overhead.
	// The pool size increases in steps of 8 packets with an initial size of 8 packets.
	// These 8 packets are allocated initially.
	// The packets 9-xx are allocated on demand
	unsigned allocatedPackets = XM_PACKET_POOL_GRANULARITY;
	XMRTPPacket **packets =  (XMRTPPacket **)malloc(allocatedPackets * sizeof(XMRTPPacket *));
	unsigned packetIndex = 0;
	for(unsigned i = 0; i < allocatedPackets; i++)
	{
		packets[i] = new XMRTPPacket(source.GetDataSize());
	}

	// make sure the RTP session does NOT ignore out of order packets
	OpalRTPMediaStream & rtpStream = (OpalRTPMediaStream &)source;
	rtpStream.GetRtpSession().SetIgnoreOutOfOrderPackets(FALSE);

	BYTE *frameBuffer = (BYTE *)malloc(sizeof(BYTE) * XM_FRAME_BUFFER_SIZE);

	// Read the first packet
	BOOL firstReadSuccesful = source.ReadPacket(*(packets[0]));

    // Access the media format
    const OpalMediaFormat & mediaFormat = source.GetMediaFormat();

	if(firstReadSuccesful == TRUE)
	{
		// Tell the media receiver to prepare processing packets
		XMCodecIdentifier codecIdentifier = _XMGetMediaFormatCodec(mediaFormat);
        unsigned sessionID = 2;

		RTP_DataFrame::PayloadTypes payloadType = packets[0]->GetPayloadType();

		// initialize the packet processing variables
		DWORD currentTimestamp = packets[0]->GetTimestamp();
		WORD firstSeqNrOfPacketGroup = 0;
		XMRTPPacket *firstPacketOfPacketGroup = NULL;
		XMRTPPacket *lastPacketOfPacketGroup = NULL;

		switch(codecIdentifier)
		{
			case XMCodecIdentifier_H261:
				packetReassembler = new XMH261RTPPacketReassembler();
				break;
			case XMCodecIdentifier_H263:
				if(_XMGetIsRFC2429(mediaFormat) || mediaFormat == XM_MEDIA_FORMAT_H263PLUS)
				{
					cout << "Receiving RFC2429" << endl;
					packetReassembler = new XMH263PlusRTPPacketReassembler();
				}
				else
				{
					int result = _XMDetermineH263PacketizationScheme(packets[0]->GetPayloadPtr(), packets[0]->GetPayloadSize());

					if(result == 0)
					{
                        // cannot determine. Last hope is to look at the payload code
						if(payloadType == RTP_DataFrame::H263)
						{
							cout << "Receiving RFC2190" << endl;
							packetReassembler = new XMH263RTPPacketReassembler();
						}
						else
						{
							cout << "Receiving RFC2429" << endl;
							packetReassembler = new XMH263PlusRTPPacketReassembler();
						}
					}
					else if(result == 1)
					{
						cout << "Receiving RFC2190" << endl;
						packetReassembler = new XMH263RTPPacketReassembler();
					}
					else
					{
						cout << "Receiving RFC2429" << endl;
						packetReassembler = new XMH263PlusRTPPacketReassembler();
					}
				}
				break;
			case XMCodecIdentifier_H264:
				packetReassembler = new XMH264RTPPacketReassembler();
				break;
			default:
				break;
		}

		_XMStartMediaReceiving(sessionID, codecIdentifier);

		// loop to receive packets and process them
		do {
			inUse.Wait();

			BOOL processingSuccessful = TRUE;
			unsigned numberOfPacketsToRelease = 0;

			XMRTPPacket *packet = packets[packetIndex];

			packet->next = NULL;
			packet->prev = NULL;

			// processing the packet
			DWORD timestamp = packet->GetTimestamp();
			WORD sequenceNumber = packet->GetSequenceNumber();

			// take into account that the timestamp might wrap around
			if(timestamp < currentTimestamp && (currentTimestamp - timestamp) > (0x01 << 31))
			{
				// This packet group is already processed
				// By changing the sequenceNumber parameter,
				// we can adjust the expected beginning of
				// the current packet group.
				if(firstSeqNrOfPacketGroup <= sequenceNumber)
				{
					firstSeqNrOfPacketGroup = sequenceNumber + 1;
				}
			}
			else
			{
				// also take into account that the timestamp might wrap around
				if(timestamp > currentTimestamp || (timestamp < currentTimestamp && (currentTimestamp - timestamp) > (0x01 << 31)))
				{
					if(firstPacketOfPacketGroup != NULL)
					{
						// Try to process the old packet although not complete
						BOOL result = TRUE;
						PINDEX frameBufferSize = 0;

						result = packetReassembler->CopyIncompletePacketsIntoFrameBuffer(firstPacketOfPacketGroup, frameBuffer, &frameBufferSize);

						if(result == TRUE)
						{
							_XMProcessFrame(sessionID, frameBuffer, frameBufferSize);
						}

						firstSeqNrOfPacketGroup = lastPacketOfPacketGroup->GetSequenceNumber() + 1;
						firstPacketOfPacketGroup = NULL;
						lastPacketOfPacketGroup = NULL;
						processingSuccessful = FALSE;
						PTRACE(1, "XMeetingReceiverMediaPatch\tIncomplete old packet group");

						// There are (packetIndex + 1) packets in the buffer, but only the last one
						// ist still needed
						numberOfPacketsToRelease = packetIndex;
					}

					currentTimestamp = timestamp;
				}

				if(lastPacketOfPacketGroup != NULL)
				{
					XMRTPPacket *previousPacket = lastPacketOfPacketGroup;

					do {
						WORD previousSequenceNumber = previousPacket->GetSequenceNumber();

						// take into account that the sequence number might wrap around
						if(sequenceNumber > previousSequenceNumber ||
						   (sequenceNumber < previousSequenceNumber && (previousSequenceNumber - sequenceNumber) > (0x01 << 15)))
						{
							// ordering is correct, insert at this point
							packet->next = previousPacket->next;
							previousPacket->next = packet;
							packet->prev = previousPacket;

							if(previousPacket == lastPacketOfPacketGroup)
							{
								lastPacketOfPacketGroup = packet;
							}

							break;
						}
						else if(sequenceNumber == previousSequenceNumber)
						{
							break;
						}

						if(previousPacket == firstPacketOfPacketGroup)
						{
							// inserting this packet at the beginning of
							// the packet group
							packet->next = previousPacket;
							previousPacket->prev = packet;
							firstPacketOfPacketGroup = packet;
							break;
						}

						previousPacket = previousPacket->prev;

					} while(TRUE);
				}
				else
				{
					firstPacketOfPacketGroup = packet;
					lastPacketOfPacketGroup = packet;
				}
			}

			/////////////////////////////////////////////////////////
			// checking whether the packet group is complete or not
			/////////////////////////////////////////////////////////
			BOOL packetGroupIsComplete = FALSE;

			WORD expectedSequenceNumber = firstSeqNrOfPacketGroup;
			XMRTPPacket *thePacket = firstPacketOfPacketGroup;

			BOOL isFirstPacket = FALSE;

			if(expectedSequenceNumber == thePacket->GetSequenceNumber())
			{
				isFirstPacket = TRUE;
			}
			else
			{
				// the sequence number is not the expected one. Try to analyze
				// the bitstream to determine whether this is the first packet
				// of a packet group or not
				isFirstPacket = packetReassembler->IsFirstPacketOfFrame(thePacket);
			}
			if(isFirstPacket == TRUE)
			{
				expectedSequenceNumber = thePacket->GetSequenceNumber();

				do {
					if(expectedSequenceNumber != thePacket->GetSequenceNumber())
					{
						break;
					}

					expectedSequenceNumber++;

					if(thePacket->next == NULL)
					{
						// no more packets in the packet group.
						// If the marker bit is set, we're complete
						if(thePacket->GetMarker() == TRUE)
						{
							packetGroupIsComplete = TRUE;
						}
						break;
					}

					thePacket = thePacket->next;

				} while(TRUE);
			}

			/////////////////////////////////////////////////////
			// If the packet group is complete, copy the packets
			// into a frame and send it to the XMMediaReceiver
			// system.
			/////////////////////////////////////////////////////

			if(packetGroupIsComplete == TRUE)
			{
				BOOL result = TRUE;
				PINDEX frameBufferSize = 0;

				result = packetReassembler->CopyPacketsIntoFrameBuffer(firstPacketOfPacketGroup, frameBuffer, &frameBufferSize);

				if(result == TRUE)
				{
					result = _XMProcessFrame(sessionID, frameBuffer, frameBufferSize);
					if(result == FALSE)
					{
						PTRACE(1, "XMeetingReceiverMediaPatch\tDecompression of the frame failed");
						processingSuccessful = FALSE;
					}
				}
				else
				{
					PTRACE(1, "XMeetingReceiverMediaPatch\tCould not copy packets into frame buffer");
					processingSuccessful = FALSE;
				}
				firstSeqNrOfPacketGroup = lastPacketOfPacketGroup->GetSequenceNumber() + 1;
				firstPacketOfPacketGroup = NULL;
				lastPacketOfPacketGroup = NULL;

				// Release all packets in the pool
				numberOfPacketsToRelease = packetIndex + 1;
			}

			if(processingSuccessful == FALSE)
			{
				IssueVideoUpdatePictureCommand();
                processingSuccessful = TRUE;
			}

			// Of not all packets can be released, the remaining packets are
			// put at the beginning of the packet pool.
			if(numberOfPacketsToRelease != 0)
			{
				unsigned i;
				for(i = 0; i < (packetIndex + 1 - numberOfPacketsToRelease); i++)
				{
					// swapping the remaining frames
					XMRTPPacket *packet = packets[i];
					packets[i] = packets[i + numberOfPacketsToRelease];
					packets[i + numberOfPacketsToRelease] = packet;
				}
				packetIndex = packetIndex + 1 - numberOfPacketsToRelease;
			}
			else
			{
				// increment the packetIndex, allocate a new XMRTPPacket if needed.
				// Also increase the size of the packet pool if required
				packetIndex++;
				if(packetIndex == allocatedPackets)
				{
					if(allocatedPackets % XM_PACKET_POOL_GRANULARITY == 0)
					{
						packets = (XMRTPPacket **)realloc(packets, (allocatedPackets + XM_PACKET_POOL_GRANULARITY) * sizeof(XMRTPPacket *));
					}

					packets[packetIndex] = new XMRTPPacket(source.GetDataSize());
					allocatedPackets++;
				}
			}

			// check for loop termination conditions
			PINDEX len = sinks.GetSize();

			inUse.Signal();

			if(len == 0)
			{
				break;
			}

		} while(source.ReadPacket(*(packets[packetIndex])) == TRUE);

		// End the media processing
		_XMStopMediaReceiving(sessionID);
	}

	// release the used RTP_DataFrames
	for(unsigned i = 0; i < allocatedPackets; i++)
	{
		XMRTPPacket *dataFrame = packets[i];
		delete dataFrame;
	}
	free(packets);
	free(frameBuffer);
	if(packetReassembler != NULL)
	{
		free(packetReassembler);
	}
}

void XMReceiverMediaPatch::IssueVideoUpdatePictureCommand()
{
	OpalVideoUpdatePicture command = OpalVideoUpdatePicture(-1, -1, -1);

    sinks[0].stream->ExecuteCommand(command);
}
<commit_msg>Prevent sending fast update picture commands if there is no sink stream<commit_after>/*
 * $Id: XMReceiverMediaPatch.cpp,v 1.31 2007/02/16 14:13:51 hfriederich Exp $
 *
 * Copyright (c) 2005-2007 XMeeting Project ("http://xmeeting.sf.net").
 * All rights reserved.
 * Copyright (c) 2005-2007 Hannes Friederich. All rights reserved.
 */

#include "XMReceiverMediaPatch.h"

#include <opal/mediastrm.h>
#include <opal/mediacmd.h>

#include "XMMediaFormats.h"
#include "XMMediaStream.h"
#include "XMCallbackBridge.h"

#include "XMAudioTester.h"

#define XM_PACKET_POOL_GRANULARITY 8
#define XM_FRAME_BUFFER_SIZE 352*288*4

XMReceiverMediaPatch::XMReceiverMediaPatch(OpalMediaStream & src)
: OpalMediaPatch(src)
{
	packetReassembler = NULL;
}

XMReceiverMediaPatch::~XMReceiverMediaPatch()
{
}

void XMReceiverMediaPatch::Start()
{
	// quit any running audio test if needed
	XMAudioTester::Stop();

	OpalMediaPatch::Start();
}

void XMReceiverMediaPatch::Main()
{
	///////////////////////////////////////////////////////////////////////////////////////////////
	// The receiving algorithm tries to achieve best-possible data integrity and builds upon
	// the following assumptions:
	//
	// 1) The chance for packets actually being lost/dropped is very small
	// 2) The chance of packets being delayed across timestamp boundaries is much smaller than
	//    the chance of packets being reordered within the same timestamp (the same video frame)
	//
	// First, the frames will be read and put into a sorted linked list with ascending sequence
	// numbers. If a packet group is complete, the packet payloads are copied together and the
	// resulting frame is sent to the XMMediaReceiver class for decompression and display.
	// A packet group is considered to be complete IF
	//
	// a) The first packet has the next ascending sequence number to the sequence number of the
	//    last packet of the previous packet group or the packet contains the beginning of a
	//    coded frame (picture start codes in H.261 / H.263) AND
	// b) The sequence numbers of the packets in the list are ascending with no sequence number
	//    missing AND
	// c) The last packet has the marker bit set
	//
	// This algorithm makes it possible to process packets of a packet group even if they arrive
	// after the last packet of the packet group with the marker bit set. This works well if
	// assumptions 1) and 2) are true.
	//
	// If a packet group is incomplete and the first packet of the next packet group arrives
	// (indicated by a different timestamp), the incomplete packet group is either dropped
	// or processed, depending on the codec being used. If the incomplete packet group is
	// processed, the processing happens delayed since the first packet of the next packet
	// group arrived, leading to inconstant display intervals. As long as assumption 1)
	// is met, this is not a big drawback.
	//
	// If either packets are missing or the decompression of the frame fails, an
	// fast update request is being sent to the remote party.
	///////////////////////////////////////////////////////////////////////////////////////////////

	// Allocating a pool of XMRTPPacket instances to reduce
	// buffer allocation overhead.
	// The pool size increases in steps of 8 packets with an initial size of 8 packets.
	// These 8 packets are allocated initially.
	// The packets 9-xx are allocated on demand
	unsigned allocatedPackets = XM_PACKET_POOL_GRANULARITY;
	XMRTPPacket **packets =  (XMRTPPacket **)malloc(allocatedPackets * sizeof(XMRTPPacket *));
	unsigned packetIndex = 0;
	for(unsigned i = 0; i < allocatedPackets; i++)
	{
		packets[i] = new XMRTPPacket(source.GetDataSize());
	}

	// make sure the RTP session does NOT ignore out of order packets
	OpalRTPMediaStream & rtpStream = (OpalRTPMediaStream &)source;
	rtpStream.GetRtpSession().SetIgnoreOutOfOrderPackets(FALSE);

	BYTE *frameBuffer = (BYTE *)malloc(sizeof(BYTE) * XM_FRAME_BUFFER_SIZE);

	// Read the first packet
	BOOL firstReadSuccesful = source.ReadPacket(*(packets[0]));

    // Access the media format
    const OpalMediaFormat & mediaFormat = source.GetMediaFormat();

	if(firstReadSuccesful == TRUE)
	{
		// Tell the media receiver to prepare processing packets
		XMCodecIdentifier codecIdentifier = _XMGetMediaFormatCodec(mediaFormat);
        unsigned sessionID = 2;

		RTP_DataFrame::PayloadTypes payloadType = packets[0]->GetPayloadType();

		// initialize the packet processing variables
		DWORD currentTimestamp = packets[0]->GetTimestamp();
		WORD firstSeqNrOfPacketGroup = 0;
		XMRTPPacket *firstPacketOfPacketGroup = NULL;
		XMRTPPacket *lastPacketOfPacketGroup = NULL;

		switch(codecIdentifier)
		{
			case XMCodecIdentifier_H261:
				packetReassembler = new XMH261RTPPacketReassembler();
				break;
			case XMCodecIdentifier_H263:
				if(_XMGetIsRFC2429(mediaFormat) || mediaFormat == XM_MEDIA_FORMAT_H263PLUS)
				{
					cout << "Receiving RFC2429" << endl;
					packetReassembler = new XMH263PlusRTPPacketReassembler();
				}
				else
				{
					int result = _XMDetermineH263PacketizationScheme(packets[0]->GetPayloadPtr(), packets[0]->GetPayloadSize());

					if(result == 0)
					{
                        // cannot determine. Last hope is to look at the payload code
						if(payloadType == RTP_DataFrame::H263)
						{
							cout << "Receiving RFC2190" << endl;
							packetReassembler = new XMH263RTPPacketReassembler();
						}
						else
						{
							cout << "Receiving RFC2429" << endl;
							packetReassembler = new XMH263PlusRTPPacketReassembler();
						}
					}
					else if(result == 1)
					{
						cout << "Receiving RFC2190" << endl;
						packetReassembler = new XMH263RTPPacketReassembler();
					}
					else
					{
						cout << "Receiving RFC2429" << endl;
						packetReassembler = new XMH263PlusRTPPacketReassembler();
					}
				}
				break;
			case XMCodecIdentifier_H264:
				packetReassembler = new XMH264RTPPacketReassembler();
				break;
			default:
				break;
		}

		_XMStartMediaReceiving(sessionID, codecIdentifier);

		// loop to receive packets and process them
		do {
			inUse.Wait();

			BOOL processingSuccessful = TRUE;
			unsigned numberOfPacketsToRelease = 0;

			XMRTPPacket *packet = packets[packetIndex];

			packet->next = NULL;
			packet->prev = NULL;

			// processing the packet
			DWORD timestamp = packet->GetTimestamp();
			WORD sequenceNumber = packet->GetSequenceNumber();

			// take into account that the timestamp might wrap around
			if(timestamp < currentTimestamp && (currentTimestamp - timestamp) > (0x01 << 31))
			{
				// This packet group is already processed
				// By changing the sequenceNumber parameter,
				// we can adjust the expected beginning of
				// the current packet group.
				if(firstSeqNrOfPacketGroup <= sequenceNumber)
				{
					firstSeqNrOfPacketGroup = sequenceNumber + 1;
				}
			}
			else
			{
				// also take into account that the timestamp might wrap around
				if(timestamp > currentTimestamp || (timestamp < currentTimestamp && (currentTimestamp - timestamp) > (0x01 << 31)))
				{
					if(firstPacketOfPacketGroup != NULL)
					{
						// Try to process the old packet although not complete
						BOOL result = TRUE;
						PINDEX frameBufferSize = 0;

						result = packetReassembler->CopyIncompletePacketsIntoFrameBuffer(firstPacketOfPacketGroup, frameBuffer, &frameBufferSize);

						if(result == TRUE)
						{
							_XMProcessFrame(sessionID, frameBuffer, frameBufferSize);
						}

						firstSeqNrOfPacketGroup = lastPacketOfPacketGroup->GetSequenceNumber() + 1;
						firstPacketOfPacketGroup = NULL;
						lastPacketOfPacketGroup = NULL;
						processingSuccessful = FALSE;
						PTRACE(1, "XMeetingReceiverMediaPatch\tIncomplete old packet group");

						// There are (packetIndex + 1) packets in the buffer, but only the last one
						// ist still needed
						numberOfPacketsToRelease = packetIndex;
					}

					currentTimestamp = timestamp;
				}

				if(lastPacketOfPacketGroup != NULL)
				{
					XMRTPPacket *previousPacket = lastPacketOfPacketGroup;

					do {
						WORD previousSequenceNumber = previousPacket->GetSequenceNumber();

						// take into account that the sequence number might wrap around
						if(sequenceNumber > previousSequenceNumber ||
						   (sequenceNumber < previousSequenceNumber && (previousSequenceNumber - sequenceNumber) > (0x01 << 15)))
						{
							// ordering is correct, insert at this point
							packet->next = previousPacket->next;
							previousPacket->next = packet;
							packet->prev = previousPacket;

							if(previousPacket == lastPacketOfPacketGroup)
							{
								lastPacketOfPacketGroup = packet;
							}

							break;
						}
						else if(sequenceNumber == previousSequenceNumber)
						{
							break;
						}

						if(previousPacket == firstPacketOfPacketGroup)
						{
							// inserting this packet at the beginning of
							// the packet group
							packet->next = previousPacket;
							previousPacket->prev = packet;
							firstPacketOfPacketGroup = packet;
							break;
						}

						previousPacket = previousPacket->prev;

					} while(TRUE);
				}
				else
				{
					firstPacketOfPacketGroup = packet;
					lastPacketOfPacketGroup = packet;
				}
			}

			/////////////////////////////////////////////////////////
			// checking whether the packet group is complete or not
			/////////////////////////////////////////////////////////
			BOOL packetGroupIsComplete = FALSE;

			WORD expectedSequenceNumber = firstSeqNrOfPacketGroup;
			XMRTPPacket *thePacket = firstPacketOfPacketGroup;

			BOOL isFirstPacket = FALSE;

			if(expectedSequenceNumber == thePacket->GetSequenceNumber())
			{
				isFirstPacket = TRUE;
			}
			else
			{
				// the sequence number is not the expected one. Try to analyze
				// the bitstream to determine whether this is the first packet
				// of a packet group or not
				isFirstPacket = packetReassembler->IsFirstPacketOfFrame(thePacket);
			}
			if(isFirstPacket == TRUE)
			{
				expectedSequenceNumber = thePacket->GetSequenceNumber();

				do {
					if(expectedSequenceNumber != thePacket->GetSequenceNumber())
					{
						break;
					}

					expectedSequenceNumber++;

					if(thePacket->next == NULL)
					{
						// no more packets in the packet group.
						// If the marker bit is set, we're complete
						if(thePacket->GetMarker() == TRUE)
						{
							packetGroupIsComplete = TRUE;
						}
						break;
					}

					thePacket = thePacket->next;

				} while(TRUE);
			}

			/////////////////////////////////////////////////////
			// If the packet group is complete, copy the packets
			// into a frame and send it to the XMMediaReceiver
			// system.
			/////////////////////////////////////////////////////

			if(packetGroupIsComplete == TRUE)
			{
				BOOL result = TRUE;
				PINDEX frameBufferSize = 0;

				result = packetReassembler->CopyPacketsIntoFrameBuffer(firstPacketOfPacketGroup, frameBuffer, &frameBufferSize);

				if(result == TRUE)
				{
					result = _XMProcessFrame(sessionID, frameBuffer, frameBufferSize);
					if(result == FALSE)
					{
						PTRACE(1, "XMeetingReceiverMediaPatch\tDecompression of the frame failed");
						processingSuccessful = FALSE;
					}
				}
				else
				{
					PTRACE(1, "XMeetingReceiverMediaPatch\tCould not copy packets into frame buffer");
					processingSuccessful = FALSE;
				}
				firstSeqNrOfPacketGroup = lastPacketOfPacketGroup->GetSequenceNumber() + 1;
				firstPacketOfPacketGroup = NULL;
				lastPacketOfPacketGroup = NULL;

				// Release all packets in the pool
				numberOfPacketsToRelease = packetIndex + 1;
			}

			if(processingSuccessful == FALSE)
			{
				IssueVideoUpdatePictureCommand();
                processingSuccessful = TRUE;
			}

			// Of not all packets can be released, the remaining packets are
			// put at the beginning of the packet pool.
			if(numberOfPacketsToRelease != 0)
			{
				unsigned i;
				for(i = 0; i < (packetIndex + 1 - numberOfPacketsToRelease); i++)
				{
					// swapping the remaining frames
					XMRTPPacket *packet = packets[i];
					packets[i] = packets[i + numberOfPacketsToRelease];
					packets[i + numberOfPacketsToRelease] = packet;
				}
				packetIndex = packetIndex + 1 - numberOfPacketsToRelease;
			}
			else
			{
				// increment the packetIndex, allocate a new XMRTPPacket if needed.
				// Also increase the size of the packet pool if required
				packetIndex++;
				if(packetIndex == allocatedPackets)
				{
					if(allocatedPackets % XM_PACKET_POOL_GRANULARITY == 0)
					{
						packets = (XMRTPPacket **)realloc(packets, (allocatedPackets + XM_PACKET_POOL_GRANULARITY) * sizeof(XMRTPPacket *));
					}

					packets[packetIndex] = new XMRTPPacket(source.GetDataSize());
					allocatedPackets++;
				}
			}

			// check for loop termination conditions
			PINDEX len = sinks.GetSize();

			inUse.Signal();

			if(len == 0)
			{
				break;
			}

		} while(source.ReadPacket(*(packets[packetIndex])) == TRUE);

		// End the media processing
		_XMStopMediaReceiving(sessionID);
	}

	// release the used RTP_DataFrames
	for(unsigned i = 0; i < allocatedPackets; i++)
	{
		XMRTPPacket *dataFrame = packets[i];
		delete dataFrame;
	}
	free(packets);
	free(frameBuffer);
	if(packetReassembler != NULL)
	{
		free(packetReassembler);
	}
}

void XMReceiverMediaPatch::IssueVideoUpdatePictureCommand()
{
    if(sinks.GetSize() == 0) {
        return;
    }

	OpalVideoUpdatePicture command = OpalVideoUpdatePicture(-1, -1, -1);

    sinks[0].stream->ExecuteCommand(command);
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    string reverseVowels(string s) {
        for (int i = 0, j = s.length() - 1; i < j;) {
            if (is_vowel(tolower(s[i])) &&
                is_vowel(tolower(s[j]))) {
                swap(s[i++], s[j--]);
            } else if (!is_vowel(tolower(s[i]))) {
                ++i;
            } else {
                --j;
            }
        }
        return s;
    }

private:
    const string vowels_ = "aeiou";
    bool is_vowel(char a){
        return vowels_.find(a) != string::npos;
    }
};
<commit_msg>Update reverse-vowels-of-a-string.cpp<commit_after>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    string reverseVowels(string s) {
        for (int i = 0, j = s.length() - 1; i < j;) {
            if (!is_vowel(tolower(s[i]))) {
                ++i;
            } else if (!is_vowel(tolower(s[j]))) {
                --j;
            } else {
                swap(s[i++], s[j--]);
            }
        }
        return s;
    }

private:
    const string vowels_ = "aeiou";
    bool is_vowel(char a){
        return vowels_.find(a) != string::npos;
    }
};
<|endoftext|>


<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2015 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <QDir>
#include <QtQml>
#include <QFile>
#include <QtDebug>
#include <QUuid>
#include <QDateTime>
#include <QSettings>
#include <QTextStream>
#include <QQmlContext>
#include <QApplication>
#include <QStandardPaths>
#include <QQmlApplicationEngine>
//-------------------------------------
#include "SpellCheck/spellchecksuggestionmodel.h"
#include "Models/filteredartitemsproxymodel.h"
#include "Suggestion/suggestionqueryengine.h"
#include "Conectivity/analyticsuserevent.h"
#include "SpellCheck/spellcheckerservice.h"
#include "Models/recentdirectoriesmodel.h"
#include "Suggestion/keywordssuggestor.h"
#include "Models/combinedartworksmodel.h"
#include "Conectivity/telemetryservice.h"
#include "Helpers/globalimageprovider.h"
#include "Models/uploadinforepository.h"
#include "Helpers/backupsaverservice.h"
#include "Helpers/helpersqmlwrapper.h"
#include "Encryption/secretsmanager.h"
#include "Models/artworksrepository.h"
#include "Helpers/settingsprovider.h"
#include "UndoRedo/undoredomanager.h"
#include "Helpers/clipboardhelper.h"
#include "Commands/commandmanager.h"
#include "Suggestion/locallibrary.h"
#include "Models/artworkuploader.h"
#include "Models/warningsmanager.h"
#include "Helpers/loggingworker.h"
#include "Helpers/updateservice.h"
#include "Models/artitemsmodel.h"
#include "Models/settingsmodel.h"
#include "Models/iptcprovider.h"
#include "Helpers/appsettings.h"
#include "Models/ziparchiver.h"
#include "Helpers/constants.h"
#include "Encryption/aes-qt.h"
#include "Helpers/runguard.h"
#include "Models/logsmodel.h"
#include "Helpers/logger.h"
#include "Common/version.h"
#include "Common/defines.h"

#ifdef WITH_LOGS

void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    Q_UNUSED(context);

    QString txt;
    switch (type) {
    case QtDebugMsg:
        txt = QString("Debug: %1").arg(msg);
        break;
    case QtWarningMsg:
        txt = QString("Warning: %1").arg(msg);
        break;
    case QtCriticalMsg:
        txt = QString("Critical: %1").arg(msg);
        break;
    case QtFatalMsg:
        txt = QString("Fatal: %1").arg(msg);
        break;
    }

    QString logLine = QString("%1 - %2")
            .arg(QDateTime::currentDateTimeUtc().toString("dd.MM.yyyy hh:mm:ss.zzz"))
            .arg(txt);

    Helpers::Logger &logger = Helpers::Logger::getInstance();
    logger.log(logLine);

    if (type == QtFatalMsg) {
        abort();
    }
}

#endif

#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)

void initQSettings() {
    QCoreApplication::setOrganizationName(Constants::ORGANIZATION_NAME);
    QCoreApplication::setOrganizationDomain(Constants::ORGANIZATION_DOMAIN);
    QCoreApplication::setApplicationName(Constants::APPLICATION_NAME);
    QString appVersion(STRINGIZE(BUILDNUMBER));
    QCoreApplication::setApplicationVersion(STRINGIZE(XPIKS_VERSION)" "STRINGIZE(XPIKS_VERSION_SUFFIX)" - " + appVersion.left(10));
}

void ensureUserIdExists(Helpers::AppSettings *settings) {
    QLatin1String userIdKey = QLatin1String(Constants::USER_AGENT_ID);
    if (!settings->contains(userIdKey)) {
        QUuid uuid = QUuid::createUuid();
        settings->setValue(userIdKey, uuid.toString());
    }
}

int main(int argc, char *argv[]) {
    Helpers::RunGuard guard("xpiks");
    if (!guard.tryToRun()) {
        std::cerr << "Xpiks is already running";
        return -1;
    }

    initQSettings();
    Helpers::AppSettings appSettings;
    ensureUserIdExists(&appSettings);

    Suggestion::LocalLibrary localLibrary;

    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    if (!appDataPath.isEmpty()) {
        QDir appDataDir(appDataPath);

        QString logFilePath = appDataDir.filePath(Constants::LOG_FILENAME);
        Helpers::Logger &logger = Helpers::Logger::getInstance();
        logger.setLogFilePath(logFilePath);

        QString libraryFilePath = appDataDir.filePath(Constants::LIBRARY_FILENAME);
        localLibrary.setLibraryPath(libraryFilePath);
    }

    Models::LogsModel logsModel;
    logsModel.startLogging();

#ifdef WITH_LOGS
    QString logFileDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    if (!logFileDir.isEmpty()) {
        QDir dir(logFileDir);
        if (!dir.exists()) {
            bool created = QDir().mkpath(logFileDir);
            Q_UNUSED(created);
        }
    }

    qInstallMessageHandler(myMessageHandler);
    qDebug() << "Log started";
#endif
    QApplication app(argc, argv);

    localLibrary.loadLibraryAsync();

    QString userId = appSettings.value(QLatin1String(Constants::USER_AGENT_ID)).toString();
    userId.remove(QRegExp("[{}-]."));

    Models::ArtworksRepository artworkRepository;
    Models::ArtItemsModel artItemsModel;
    Models::CombinedArtworksModel combinedArtworksModel;
    Models::IptcProvider iptcProvider;
    iptcProvider.setLocalLibrary(&localLibrary);
    Models::UploadInfoRepository uploadInfoRepository;
    Models::WarningsManager warningsManager;
    Models::SettingsModel settingsModel;
    settingsModel.readAllValues();
    Encryption::SecretsManager secretsManager;
    UndoRedo::UndoRedoManager undoRedoManager;
    Models::ZipArchiver zipArchiver;
    Suggestion::KeywordsSuggestor keywordsSuggestor;
    keywordsSuggestor.setLocalLibrary(&localLibrary);
    Models::FilteredArtItemsProxyModel filteredArtItemsModel;
    filteredArtItemsModel.setSourceModel(&artItemsModel);
    Models::RecentDirectoriesModel recentDirectorieModel;
    Models::ArtworkUploader artworkUploader(settingsModel.getMaxParallelUploads());
    SpellCheck::SpellCheckerService spellCheckerService;
    SpellCheck::SpellCheckSuggestionModel spellCheckSuggestionModel;
    Helpers::BackupSaverService metadataSaverService;
    Helpers::UpdateService updateService;

    const QString reportingEndpoint = QLatin1String("cc39a47f60e1ed812e2403b33678dd1c529f1cc43f66494998ec478a4d13496269a3dfa01f882941766dba246c76b12b2a0308e20afd84371c41cf513260f8eb8b71f8c472cafb1abf712c071938ec0791bbf769ab9625c3b64827f511fa3fbb");
    QString endpoint = Encryption::decodeText(reportingEndpoint, "reporting");
    Conectivity::TelemetryService telemetryService(userId, endpoint);

    Commands::CommandManager commandManager;
    commandManager.InjectDependency(&artworkRepository);
    commandManager.InjectDependency(&artItemsModel);
    commandManager.InjectDependency(&filteredArtItemsModel);
    commandManager.InjectDependency(&combinedArtworksModel);
    commandManager.InjectDependency(&iptcProvider);
    commandManager.InjectDependency(&artworkUploader);
    commandManager.InjectDependency(&uploadInfoRepository);
    commandManager.InjectDependency(&warningsManager);
    commandManager.InjectDependency(&secretsManager);
    commandManager.InjectDependency(&undoRedoManager);
    commandManager.InjectDependency(&zipArchiver);
    commandManager.InjectDependency(&keywordsSuggestor);
    commandManager.InjectDependency(&settingsModel);
    commandManager.InjectDependency(&recentDirectorieModel);
    commandManager.InjectDependency(&spellCheckerService);
    commandManager.InjectDependency(&spellCheckSuggestionModel);
    commandManager.InjectDependency(&metadataSaverService);
    commandManager.InjectDependency(&telemetryService);
    commandManager.InjectDependency(&updateService);

    // other initializations
    secretsManager.setMasterPasswordHash(appSettings.value(Constants::MASTER_PASSWORD_HASH, "").toString());
    uploadInfoRepository.initFromString(appSettings.value(Constants::UPLOAD_HOSTS, "").toString());
    recentDirectorieModel.deserializeFromSettings(appSettings.value(Constants::RECENT_DIRECTORIES, "").toString());

    Helpers::SettingsProvider::getInstance().setSettingsModelInstance(&settingsModel);

    commandManager.connectEntitiesSignalsSlots();

    qmlRegisterType<Helpers::ClipboardHelper>("xpiks", 1, 0, "ClipboardHelper");

    QQmlApplicationEngine engine;
    Helpers::GlobalImageProvider *globalProvider = new Helpers::GlobalImageProvider(QQmlImageProviderBase::Image);

    Helpers::HelpersQmlWrapper helpersQmlWrapper(&commandManager);

    QQmlContext *rootContext = engine.rootContext();
    rootContext->setContextProperty("artItemsModel", &artItemsModel);
    rootContext->setContextProperty("artworkRepository", &artworkRepository);
    rootContext->setContextProperty("combinedArtworks", &combinedArtworksModel);
    rootContext->setContextProperty("appSettings", &appSettings);
    rootContext->setContextProperty("iptcProvider", &iptcProvider);
    rootContext->setContextProperty("artworkUploader", &artworkUploader);
    rootContext->setContextProperty("uploadInfos", &uploadInfoRepository);
    rootContext->setContextProperty("logsModel", &logsModel);
    rootContext->setContextProperty("warningsManager", &warningsManager);
    rootContext->setContextProperty("secretsManager", &secretsManager);
    rootContext->setContextProperty("undoRedoManager", &undoRedoManager);
    rootContext->setContextProperty("zipArchiver", &zipArchiver);
    rootContext->setContextProperty("keywordsSuggestor", &keywordsSuggestor);
    rootContext->setContextProperty("settingsModel", &settingsModel);
    rootContext->setContextProperty("filteredArtItemsModel", &filteredArtItemsModel);
    rootContext->setContextProperty("helpersWrapper", &helpersQmlWrapper);
    rootContext->setContextProperty("recentDirectories", &recentDirectorieModel);
    rootContext->setContextProperty("updateService", &updateService);
    rootContext->setContextProperty("spellCheckerService", &spellCheckerService);
    rootContext->setContextProperty("spellCheckSuggestionModel", &spellCheckSuggestionModel);

    engine.addImageProvider("global", globalProvider);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

#ifdef QT_DEBUG
    if (argc > 1) {
        QStringList pathes;
        for (int i = 1; i < argc; ++i) {
            pathes.append(QString(argv[i]));
        }
        commandManager.addInitialArtworks(pathes);
    }
#endif

    return app.exec();
}
<commit_msg>Minor fix for Release build for qt 5.5<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2015 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <QDir>
#include <QtQml>
#include <QFile>
#include <QtDebug>
#include <QUuid>
#include <QDateTime>
#include <QSettings>
#include <QTextStream>
#include <QQmlContext>
#include <QApplication>
#include <QStandardPaths>
#include <QQmlApplicationEngine>
//-------------------------------------
#include "SpellCheck/spellchecksuggestionmodel.h"
#include "Models/filteredartitemsproxymodel.h"
#include "Suggestion/suggestionqueryengine.h"
#include "Conectivity/analyticsuserevent.h"
#include "SpellCheck/spellcheckerservice.h"
#include "Models/recentdirectoriesmodel.h"
#include "Suggestion/keywordssuggestor.h"
#include "Models/combinedartworksmodel.h"
#include "Conectivity/telemetryservice.h"
#include "Helpers/globalimageprovider.h"
#include "Models/uploadinforepository.h"
#include "Helpers/backupsaverservice.h"
#include "Helpers/helpersqmlwrapper.h"
#include "Encryption/secretsmanager.h"
#include "Models/artworksrepository.h"
#include "Helpers/settingsprovider.h"
#include "UndoRedo/undoredomanager.h"
#include "Helpers/clipboardhelper.h"
#include "Commands/commandmanager.h"
#include "Suggestion/locallibrary.h"
#include "Models/artworkuploader.h"
#include "Models/warningsmanager.h"
#include "Helpers/loggingworker.h"
#include "Helpers/updateservice.h"
#include "Models/artitemsmodel.h"
#include "Models/settingsmodel.h"
#include "Models/iptcprovider.h"
#include "Helpers/appsettings.h"
#include "Models/ziparchiver.h"
#include "Helpers/constants.h"
#include "Encryption/aes-qt.h"
#include "Helpers/runguard.h"
#include "Models/logsmodel.h"
#include "Helpers/logger.h"
#include "Common/version.h"
#include "Common/defines.h"

#ifdef WITH_LOGS

void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    Q_UNUSED(context);

    QString txt;
    switch (type) {
    case QtDebugMsg:
        txt = QString("Debug: %1").arg(msg);
        break;
    case QtWarningMsg:
        txt = QString("Warning: %1").arg(msg);
        break;
    case QtCriticalMsg:
        txt = QString("Critical: %1").arg(msg);
        break;
    case QtFatalMsg:
        txt = QString("Fatal: %1").arg(msg);
        break;
    case QtInfoMsg:
        txt = QString("Info: %1").arg(msg);
        break;
    }

    QString logLine = QString("%1 - %2")
            .arg(QDateTime::currentDateTimeUtc().toString("dd.MM.yyyy hh:mm:ss.zzz"))
            .arg(txt);

    Helpers::Logger &logger = Helpers::Logger::getInstance();
    logger.log(logLine);

    if (type == QtFatalMsg) {
        abort();
    }
}

#endif

#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)

void initQSettings() {
    QCoreApplication::setOrganizationName(Constants::ORGANIZATION_NAME);
    QCoreApplication::setOrganizationDomain(Constants::ORGANIZATION_DOMAIN);
    QCoreApplication::setApplicationName(Constants::APPLICATION_NAME);
    QString appVersion(STRINGIZE(BUILDNUMBER));
    QCoreApplication::setApplicationVersion(STRINGIZE(XPIKS_VERSION)" "STRINGIZE(XPIKS_VERSION_SUFFIX)" - " + appVersion.left(10));
}

void ensureUserIdExists(Helpers::AppSettings *settings) {
    QLatin1String userIdKey = QLatin1String(Constants::USER_AGENT_ID);
    if (!settings->contains(userIdKey)) {
        QUuid uuid = QUuid::createUuid();
        settings->setValue(userIdKey, uuid.toString());
    }
}

int main(int argc, char *argv[]) {
    Helpers::RunGuard guard("xpiks");
    if (!guard.tryToRun()) {
        std::cerr << "Xpiks is already running";
        return -1;
    }

    initQSettings();
    Helpers::AppSettings appSettings;
    ensureUserIdExists(&appSettings);

    Suggestion::LocalLibrary localLibrary;

    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    if (!appDataPath.isEmpty()) {
        QDir appDataDir(appDataPath);

        QString logFilePath = appDataDir.filePath(Constants::LOG_FILENAME);
        Helpers::Logger &logger = Helpers::Logger::getInstance();
        logger.setLogFilePath(logFilePath);

        QString libraryFilePath = appDataDir.filePath(Constants::LIBRARY_FILENAME);
        localLibrary.setLibraryPath(libraryFilePath);
    }

    Models::LogsModel logsModel;
    logsModel.startLogging();

#ifdef WITH_LOGS
    QString logFileDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    if (!logFileDir.isEmpty()) {
        QDir dir(logFileDir);
        if (!dir.exists()) {
            bool created = QDir().mkpath(logFileDir);
            Q_UNUSED(created);
        }
    }

    qInstallMessageHandler(myMessageHandler);
    qDebug() << "Log started";
#endif
    QApplication app(argc, argv);

    localLibrary.loadLibraryAsync();

    QString userId = appSettings.value(QLatin1String(Constants::USER_AGENT_ID)).toString();
    userId.remove(QRegExp("[{}-]."));

    Models::ArtworksRepository artworkRepository;
    Models::ArtItemsModel artItemsModel;
    Models::CombinedArtworksModel combinedArtworksModel;
    Models::IptcProvider iptcProvider;
    iptcProvider.setLocalLibrary(&localLibrary);
    Models::UploadInfoRepository uploadInfoRepository;
    Models::WarningsManager warningsManager;
    Models::SettingsModel settingsModel;
    settingsModel.readAllValues();
    Encryption::SecretsManager secretsManager;
    UndoRedo::UndoRedoManager undoRedoManager;
    Models::ZipArchiver zipArchiver;
    Suggestion::KeywordsSuggestor keywordsSuggestor;
    keywordsSuggestor.setLocalLibrary(&localLibrary);
    Models::FilteredArtItemsProxyModel filteredArtItemsModel;
    filteredArtItemsModel.setSourceModel(&artItemsModel);
    Models::RecentDirectoriesModel recentDirectorieModel;
    Models::ArtworkUploader artworkUploader(settingsModel.getMaxParallelUploads());
    SpellCheck::SpellCheckerService spellCheckerService;
    SpellCheck::SpellCheckSuggestionModel spellCheckSuggestionModel;
    Helpers::BackupSaverService metadataSaverService;
    Helpers::UpdateService updateService;

    const QString reportingEndpoint = QLatin1String("cc39a47f60e1ed812e2403b33678dd1c529f1cc43f66494998ec478a4d13496269a3dfa01f882941766dba246c76b12b2a0308e20afd84371c41cf513260f8eb8b71f8c472cafb1abf712c071938ec0791bbf769ab9625c3b64827f511fa3fbb");
    QString endpoint = Encryption::decodeText(reportingEndpoint, "reporting");
    Conectivity::TelemetryService telemetryService(userId, endpoint);

    Commands::CommandManager commandManager;
    commandManager.InjectDependency(&artworkRepository);
    commandManager.InjectDependency(&artItemsModel);
    commandManager.InjectDependency(&filteredArtItemsModel);
    commandManager.InjectDependency(&combinedArtworksModel);
    commandManager.InjectDependency(&iptcProvider);
    commandManager.InjectDependency(&artworkUploader);
    commandManager.InjectDependency(&uploadInfoRepository);
    commandManager.InjectDependency(&warningsManager);
    commandManager.InjectDependency(&secretsManager);
    commandManager.InjectDependency(&undoRedoManager);
    commandManager.InjectDependency(&zipArchiver);
    commandManager.InjectDependency(&keywordsSuggestor);
    commandManager.InjectDependency(&settingsModel);
    commandManager.InjectDependency(&recentDirectorieModel);
    commandManager.InjectDependency(&spellCheckerService);
    commandManager.InjectDependency(&spellCheckSuggestionModel);
    commandManager.InjectDependency(&metadataSaverService);
    commandManager.InjectDependency(&telemetryService);
    commandManager.InjectDependency(&updateService);

    // other initializations
    secretsManager.setMasterPasswordHash(appSettings.value(Constants::MASTER_PASSWORD_HASH, "").toString());
    uploadInfoRepository.initFromString(appSettings.value(Constants::UPLOAD_HOSTS, "").toString());
    recentDirectorieModel.deserializeFromSettings(appSettings.value(Constants::RECENT_DIRECTORIES, "").toString());

    Helpers::SettingsProvider::getInstance().setSettingsModelInstance(&settingsModel);

    commandManager.connectEntitiesSignalsSlots();

    qmlRegisterType<Helpers::ClipboardHelper>("xpiks", 1, 0, "ClipboardHelper");

    QQmlApplicationEngine engine;
    Helpers::GlobalImageProvider *globalProvider = new Helpers::GlobalImageProvider(QQmlImageProviderBase::Image);

    Helpers::HelpersQmlWrapper helpersQmlWrapper(&commandManager);

    QQmlContext *rootContext = engine.rootContext();
    rootContext->setContextProperty("artItemsModel", &artItemsModel);
    rootContext->setContextProperty("artworkRepository", &artworkRepository);
    rootContext->setContextProperty("combinedArtworks", &combinedArtworksModel);
    rootContext->setContextProperty("appSettings", &appSettings);
    rootContext->setContextProperty("iptcProvider", &iptcProvider);
    rootContext->setContextProperty("artworkUploader", &artworkUploader);
    rootContext->setContextProperty("uploadInfos", &uploadInfoRepository);
    rootContext->setContextProperty("logsModel", &logsModel);
    rootContext->setContextProperty("warningsManager", &warningsManager);
    rootContext->setContextProperty("secretsManager", &secretsManager);
    rootContext->setContextProperty("undoRedoManager", &undoRedoManager);
    rootContext->setContextProperty("zipArchiver", &zipArchiver);
    rootContext->setContextProperty("keywordsSuggestor", &keywordsSuggestor);
    rootContext->setContextProperty("settingsModel", &settingsModel);
    rootContext->setContextProperty("filteredArtItemsModel", &filteredArtItemsModel);
    rootContext->setContextProperty("helpersWrapper", &helpersQmlWrapper);
    rootContext->setContextProperty("recentDirectories", &recentDirectorieModel);
    rootContext->setContextProperty("updateService", &updateService);
    rootContext->setContextProperty("spellCheckerService", &spellCheckerService);
    rootContext->setContextProperty("spellCheckSuggestionModel", &spellCheckSuggestionModel);

    engine.addImageProvider("global", globalProvider);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

#ifdef QT_DEBUG
    if (argc > 1) {
        QStringList pathes;
        for (int i = 1; i < argc; ++i) {
            pathes.append(QString(argv[i]));
        }
        commandManager.addInitialArtworks(pathes);
    }
#endif

    return app.exec();
}
<|endoftext|>