<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 *  Created on: Jan 2018
 *      Author: Norbert Podhorszki
 */

#include <chrono>
#include <ios>      //std::ios_base::failure
#include <iostream> //std::cout
#include <numeric>
#include <stdexcept> //std::invalid_argument std::exception
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <gtest/gtest.h>

#include <adios2.h>

static int numprocs, wrank;
std::string engineName; // comes from command line

struct RunParams
{
    /* 2D decomposition of processes
     * npx_w x npy_w Writers
     * npx_r x npy_r Readers
     */
    size_t npx_w;
    size_t npy_w;
    size_t npx_r;
    size_t npy_r;
    RunParams(size_t xw, size_t yw, size_t xr, size_t yr)
    : npx_w{xw}, npy_w{yw}, npx_r{xr}, npy_r{yr} {};
};

/* This function is executed by INSTANTIATE_TEST_CASE_P
   before main() and MPI_Init()!!! */
std::vector<RunParams> CreateRunParams()
{
    std::vector<RunParams> params;
    // 2 process test
    params.push_back(RunParams(1, 1, 1, 1));
    // 3 process tests
    params.push_back(RunParams(2, 1, 1, 1));
    params.push_back(RunParams(1, 2, 1, 1));
    params.push_back(RunParams(1, 1, 2, 1));
    params.push_back(RunParams(1, 1, 1, 2));
    // 4 process tests
    params.push_back(RunParams(2, 1, 2, 1));
    params.push_back(RunParams(2, 1, 1, 2));
    // 8 process tests
    params.push_back(RunParams(1, 1, 1, 7));
    params.push_back(RunParams(1, 7, 1, 1));
    params.push_back(RunParams(2, 2, 2, 2));
    // 16 process tests
    params.push_back(RunParams(3, 5, 1, 1));
    params.push_back(RunParams(1, 1, 5, 3));
    return params;
}

class TestStagingMPMD : public ::testing::TestWithParam<RunParams>
{
public:
    TestStagingMPMD() = default;
    const std::string streamName = "TestStream";

    void MainWriters(MPI_Comm comm, size_t npx, size_t npy, int steps,
                     unsigned int sleeptime)
    {
        int rank, nproc;
        MPI_Comm_rank(comm, &rank);
        MPI_Comm_size(comm, &nproc);
        if (!rank)
        {
            std::cout << "There are " << nproc << " Writers" << std::endl;
        }
        size_t ndx = 50;
        size_t ndy = 60;
        size_t gndx = npx * ndx;
        size_t gndy = npy * ndy;
        size_t posx = rank % npx;
        size_t posy = rank / npx;
        size_t offsx = posx * ndx;
        size_t offsy = posy * ndy;

        std::vector<float> myArray(ndx * ndy);

        adios2::ADIOS adios(comm);
        adios2::IO &io = adios.DeclareIO("writer");
        io.SetEngine(engineName);

        adios2::Variable<float> &varArray =
            io.DefineVariable<float>("myArray", {gndx, gndy}, {offsx, offsy},
                                     {ndx, ndy}, adios2::ConstantDims);

        adios2::Engine &writer = io.Open(streamName, adios2::Mode::Write, comm);

        for (size_t step = 0; step < steps; ++step)
        {
            size_t idx = 0;
            for (size_t x = 0; x < ndx; ++x)
            {
                for (size_t y = 0; y < ndy; ++y)
                {
                    myArray[idx] = GetValue(offsx + x, offsy + y, step);
                    ++idx;
                }
            }
            writer.BeginStep(adios2::StepMode::Append);
            writer.PutDeferred<float>(varArray, myArray.data());
            writer.EndStep();
            std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
        }
        writer.Close();
    }

    /* encode position x,y as y.x floating point value in each array cell
     * add 1000*step to each value
     *
     * A 2 by 2 example with 3x3 local arrays
     *   0.0    0.001  0.002 |  0.003  0.004  0.005
     *   1.0    1.001  1.002 |  1.003  1.004  1.005
     *   2.0    2.001  2.002 |  2.003  2.004  2.005
     *   --------------------+---------------------
     *   3.0    3.001  3.002 |  3.003  3.004  3.005
     *   4.0    4.001  4.002 |  4.003  4.004  4.005
     *   5.0    5.001  5.002 |  5.003  5.004  5.005
     *
     * Next step each value is bigger by 1000
     */
    float GetValue(size_t offsx, size_t offsy, size_t step)
    {
        return 1000.0f * step + offsy + offsx / 1000.0f;
    }

    void CheckData(const std::vector<float> &array, size_t gndx, size_t gndy,
                   size_t offsx, size_t offsy, size_t ndx, size_t ndy,
                   size_t step, int rank)
    {
        size_t idx = 0;
        for (size_t x = 0; x < ndx; ++x)
        {
            for (size_t y = 0; y < ndy; ++y)
            {
                float expectedValue = GetValue(offsx + x, offsy + y, step);
                EXPECT_EQ(array[idx], expectedValue) <<
                    "Error in read, did not receive the expected value:"
                    << " rank " << rank << ", step " << step
                    << ", gdim {" << gndx << ',' << gndy << '}'
                    << ", offs {" << offsx << ',' << offsy << '}'
                    << ", ldim {" << ndx << ',' << ndy << '}'
                    << ", lpos {" << x << ',' << y << '}';
                ++idx;
            }
        }
    }

    void MainReaders(MPI_Comm comm, size_t npx, size_t npy,
                     unsigned int sleeptime)
    {
        int rank, nproc;
        MPI_Comm_rank(comm, &rank);
        MPI_Comm_size(comm, &nproc);
        if (!rank)
        {
            std::cout << "There are " << nproc << " Readers" << std::endl;
        }

        adios2::ADIOS adios(comm);
        adios2::IO &io = adios.DeclareIO("reader");
        io.SetEngine(engineName);
        adios2::Engine &reader = io.Open(streamName, adios2::Mode::Read, comm);

        size_t posx = rank % npx;
        size_t posy = rank / npx;
        size_t step = 0;
        adios2::Variable<float> *vMyArray = nullptr;
        std::vector<float> myArray;

        while (true)
        {
            adios2::StepStatus status =
                reader.BeginStep(adios2::StepMode::NextAvailable, 60.0f);
            if (status != adios2::StepStatus::OK)
            {
                break;
            }

            vMyArray = io.InquireVariable<float>("myArray");
            if (vMyArray == nullptr)
            {
                throw std::ios_base::failure("Missing 'myArray' variable.");
            }

            // 2D decomposition of global array reading
            size_t gndx = vMyArray->m_Shape[0];
            size_t gndy = vMyArray->m_Shape[1];
            size_t ndx = gndx / npx;
            size_t ndy = gndy / npy;
            size_t offsx = ndx * posx;
            size_t offsy = ndy * posy;
            if (posx == npx - 1)
            {
                // right-most processes need to read all the rest of rows
                ndx = gndx - ndx * (npx - 1);
            }

            if (posy == npy - 1)
            {
                // bottom processes need to read all the rest of columns
                ndy = gndy - ndy * (npy - 1);
            }

            adios2::Dims count({ndx, ndy});
            adios2::Dims start({offsx, offsy});

            vMyArray->SetSelection({start, count});
            size_t elementsSize = count[0] * count[1];
            myArray.resize(elementsSize);

            reader.GetDeferred(*vMyArray, myArray.data());
            reader.EndStep();
            CheckData(myArray, gndx, gndy, offsx, offsy, ndx, ndy, step, rank);
            std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
            ++step;
        }
        reader.Close();
    }

    void TestCommon(RunParams p, int steps, unsigned int writer_sleeptime,
                    unsigned int reader_sleeptime)
    {
        std::cout << "test " << p.npx_w << "x" << p.npy_w << " writers "
                  << p.npx_r << "x" << p.npy_r << " readers " << std::endl;

        int nwriters = p.npx_w * p.npy_w;
        int nreaders = p.npx_r * p.npy_r;
        if (nwriters + nreaders > numprocs)
        {
            if (!wrank)
            {
                std::cout
                    << "skip test: writers+readers > available processors "
                    << std::endl;
            }
            return;
        }

        int rank;
        MPI_Comm comm;

        unsigned int color;
        if (wrank < nwriters)
        {
            color = 0; // writers
        }
        else if (wrank < nwriters + nreaders)
        {
            color = 1; // readers
        }
        else
        {
            color = 2; // not participating in test
        }
        MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &comm);
        MPI_Comm_rank(comm, &rank);

        if (color == 0)
        {
            std::cout << "Process wrank " << wrank << " rank " << rank
                      << " calls MainWriters " << std::endl;
            MainWriters(comm, p.npx_w, p.npy_w, steps, writer_sleeptime);
        }
        else if (color == 1)
        {
            std::cout << "Process wrank " << wrank << " rank " << rank
                      << " calls MainReaders " << std::endl;
            MainReaders(comm, p.npx_r, p.npy_r, reader_sleeptime);
        }
        std::cout << "Process wrank " << wrank << " rank " << rank
                  << " enters MPI barrier..." << std::endl;
        MPI_Barrier(MPI_COMM_WORLD);

        // Separate each individual test with a big gap in time
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
};

TEST_P(TestStagingMPMD, SingleStep)
{
    RunParams p = GetParam();
    TestCommon(p, 1, 0, 0);
}

TEST_P(TestStagingMPMD, MultipleSteps)
{
    RunParams p = GetParam();
    TestCommon(p, 10, 0, 0);
}

TEST_P(TestStagingMPMD, SlowWriter)
{
    RunParams p = GetParam();
    TestCommon(p, 5, 500, 0);
}

TEST_P(TestStagingMPMD, SlowReader)
{
    RunParams p = GetParam();
    TestCommon(p, 5, 0, 500);
}

INSTANTIATE_TEST_CASE_P(NxM, TestStagingMPMD,
                        ::testing::ValuesIn(CreateRunParams()));

//******************************************************************************
// main
//******************************************************************************

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    ::testing::InitGoogleTest(&argc, argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    engineName = std::string(argv[1]);

    if (!wrank)
    {
        std::cout << "Test " << engineName << " engine with " << numprocs
                  << " processes " << std::endl;
    }

    int result;
    result = RUN_ALL_TESTS();

    MPI_Finalize();
    return result;
}
<commit_msg>Formatting<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 *  Created on: Jan 2018
 *      Author: Norbert Podhorszki
 */

#include <chrono>
#include <ios>      //std::ios_base::failure
#include <iostream> //std::cout
#include <numeric>
#include <stdexcept> //std::invalid_argument std::exception
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <gtest/gtest.h>

#include <adios2.h>

static int numprocs, wrank;
std::string engineName; // comes from command line

struct RunParams
{
    /* 2D decomposition of processes
     * npx_w x npy_w Writers
     * npx_r x npy_r Readers
     */
    size_t npx_w;
    size_t npy_w;
    size_t npx_r;
    size_t npy_r;
    RunParams(size_t xw, size_t yw, size_t xr, size_t yr)
    : npx_w{xw}, npy_w{yw}, npx_r{xr}, npy_r{yr} {};
};

/* This function is executed by INSTANTIATE_TEST_CASE_P
   before main() and MPI_Init()!!! */
std::vector<RunParams> CreateRunParams()
{
    std::vector<RunParams> params;
    // 2 process test
    params.push_back(RunParams(1, 1, 1, 1));
    // 3 process tests
    params.push_back(RunParams(2, 1, 1, 1));
    params.push_back(RunParams(1, 2, 1, 1));
    params.push_back(RunParams(1, 1, 2, 1));
    params.push_back(RunParams(1, 1, 1, 2));
    // 4 process tests
    params.push_back(RunParams(2, 1, 2, 1));
    params.push_back(RunParams(2, 1, 1, 2));
    // 8 process tests
    params.push_back(RunParams(1, 1, 1, 7));
    params.push_back(RunParams(1, 7, 1, 1));
    params.push_back(RunParams(2, 2, 2, 2));
    // 16 process tests
    params.push_back(RunParams(3, 5, 1, 1));
    params.push_back(RunParams(1, 1, 5, 3));
    return params;
}

class TestStagingMPMD : public ::testing::TestWithParam<RunParams>
{
public:
    TestStagingMPMD() = default;
    const std::string streamName = "TestStream";

    void MainWriters(MPI_Comm comm, size_t npx, size_t npy, int steps,
                     unsigned int sleeptime)
    {
        int rank, nproc;
        MPI_Comm_rank(comm, &rank);
        MPI_Comm_size(comm, &nproc);
        if (!rank)
        {
            std::cout << "There are " << nproc << " Writers" << std::endl;
        }
        size_t ndx = 50;
        size_t ndy = 60;
        size_t gndx = npx * ndx;
        size_t gndy = npy * ndy;
        size_t posx = rank % npx;
        size_t posy = rank / npx;
        size_t offsx = posx * ndx;
        size_t offsy = posy * ndy;

        std::vector<float> myArray(ndx * ndy);

        adios2::ADIOS adios(comm);
        adios2::IO &io = adios.DeclareIO("writer");
        io.SetEngine(engineName);

        adios2::Variable<float> &varArray =
            io.DefineVariable<float>("myArray", {gndx, gndy}, {offsx, offsy},
                                     {ndx, ndy}, adios2::ConstantDims);

        adios2::Engine &writer = io.Open(streamName, adios2::Mode::Write, comm);

        for (size_t step = 0; step < steps; ++step)
        {
            size_t idx = 0;
            for (size_t x = 0; x < ndx; ++x)
            {
                for (size_t y = 0; y < ndy; ++y)
                {
                    myArray[idx] = GetValue(offsx + x, offsy + y, step);
                    ++idx;
                }
            }
            writer.BeginStep(adios2::StepMode::Append);
            writer.PutDeferred<float>(varArray, myArray.data());
            writer.EndStep();
            std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
        }
        writer.Close();
    }

    /* encode position x,y as y.x floating point value in each array cell
     * add 1000*step to each value
     *
     * A 2 by 2 example with 3x3 local arrays
     *   0.0    0.001  0.002 |  0.003  0.004  0.005
     *   1.0    1.001  1.002 |  1.003  1.004  1.005
     *   2.0    2.001  2.002 |  2.003  2.004  2.005
     *   --------------------+---------------------
     *   3.0    3.001  3.002 |  3.003  3.004  3.005
     *   4.0    4.001  4.002 |  4.003  4.004  4.005
     *   5.0    5.001  5.002 |  5.003  5.004  5.005
     *
     * Next step each value is bigger by 1000
     */
    float GetValue(size_t offsx, size_t offsy, size_t step)
    {
        return 1000.0f * step + offsy + offsx / 1000.0f;
    }

    void CheckData(const std::vector<float> &array, size_t gndx, size_t gndy,
                   size_t offsx, size_t offsy, size_t ndx, size_t ndy,
                   size_t step, int rank)
    {
        size_t idx = 0;
        for (size_t x = 0; x < ndx; ++x)
        {
            for (size_t y = 0; y < ndy; ++y)
            {
                float expectedValue = GetValue(offsx + x, offsy + y, step);
                EXPECT_EQ(array[idx], expectedValue)
                    << "Error in read, did not receive the expected value:"
                    << " rank " << rank << ", step " << step << ", gdim {"
                    << gndx << ',' << gndy << '}' << ", offs {" << offsx << ','
                    << offsy << '}' << ", ldim {" << ndx << ',' << ndy << '}'
                    << ", lpos {" << x << ',' << y << '}';
                ++idx;
            }
        }
    }

    void MainReaders(MPI_Comm comm, size_t npx, size_t npy,
                     unsigned int sleeptime)
    {
        int rank, nproc;
        MPI_Comm_rank(comm, &rank);
        MPI_Comm_size(comm, &nproc);
        if (!rank)
        {
            std::cout << "There are " << nproc << " Readers" << std::endl;
        }

        adios2::ADIOS adios(comm);
        adios2::IO &io = adios.DeclareIO("reader");
        io.SetEngine(engineName);
        adios2::Engine &reader = io.Open(streamName, adios2::Mode::Read, comm);

        size_t posx = rank % npx;
        size_t posy = rank / npx;
        size_t step = 0;
        adios2::Variable<float> *vMyArray = nullptr;
        std::vector<float> myArray;

        while (true)
        {
            adios2::StepStatus status =
                reader.BeginStep(adios2::StepMode::NextAvailable, 60.0f);
            if (status != adios2::StepStatus::OK)
            {
                break;
            }

            vMyArray = io.InquireVariable<float>("myArray");
            if (vMyArray == nullptr)
            {
                throw std::ios_base::failure("Missing 'myArray' variable.");
            }

            // 2D decomposition of global array reading
            size_t gndx = vMyArray->m_Shape[0];
            size_t gndy = vMyArray->m_Shape[1];
            size_t ndx = gndx / npx;
            size_t ndy = gndy / npy;
            size_t offsx = ndx * posx;
            size_t offsy = ndy * posy;
            if (posx == npx - 1)
            {
                // right-most processes need to read all the rest of rows
                ndx = gndx - ndx * (npx - 1);
            }

            if (posy == npy - 1)
            {
                // bottom processes need to read all the rest of columns
                ndy = gndy - ndy * (npy - 1);
            }

            adios2::Dims count({ndx, ndy});
            adios2::Dims start({offsx, offsy});

            vMyArray->SetSelection({start, count});
            size_t elementsSize = count[0] * count[1];
            myArray.resize(elementsSize);

            reader.GetDeferred(*vMyArray, myArray.data());
            reader.EndStep();
            CheckData(myArray, gndx, gndy, offsx, offsy, ndx, ndy, step, rank);
            std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
            ++step;
        }
        reader.Close();
    }

    void TestCommon(RunParams p, int steps, unsigned int writer_sleeptime,
                    unsigned int reader_sleeptime)
    {
        std::cout << "test " << p.npx_w << "x" << p.npy_w << " writers "
                  << p.npx_r << "x" << p.npy_r << " readers " << std::endl;

        int nwriters = p.npx_w * p.npy_w;
        int nreaders = p.npx_r * p.npy_r;
        if (nwriters + nreaders > numprocs)
        {
            if (!wrank)
            {
                std::cout
                    << "skip test: writers+readers > available processors "
                    << std::endl;
            }
            return;
        }

        int rank;
        MPI_Comm comm;

        unsigned int color;
        if (wrank < nwriters)
        {
            color = 0; // writers
        }
        else if (wrank < nwriters + nreaders)
        {
            color = 1; // readers
        }
        else
        {
            color = 2; // not participating in test
        }
        MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &comm);
        MPI_Comm_rank(comm, &rank);

        if (color == 0)
        {
            std::cout << "Process wrank " << wrank << " rank " << rank
                      << " calls MainWriters " << std::endl;
            MainWriters(comm, p.npx_w, p.npy_w, steps, writer_sleeptime);
        }
        else if (color == 1)
        {
            std::cout << "Process wrank " << wrank << " rank " << rank
                      << " calls MainReaders " << std::endl;
            MainReaders(comm, p.npx_r, p.npy_r, reader_sleeptime);
        }
        std::cout << "Process wrank " << wrank << " rank " << rank
                  << " enters MPI barrier..." << std::endl;
        MPI_Barrier(MPI_COMM_WORLD);

        // Separate each individual test with a big gap in time
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
};

TEST_P(TestStagingMPMD, SingleStep)
{
    RunParams p = GetParam();
    TestCommon(p, 1, 0, 0);
}

TEST_P(TestStagingMPMD, MultipleSteps)
{
    RunParams p = GetParam();
    TestCommon(p, 10, 0, 0);
}

TEST_P(TestStagingMPMD, SlowWriter)
{
    RunParams p = GetParam();
    TestCommon(p, 5, 500, 0);
}

TEST_P(TestStagingMPMD, SlowReader)
{
    RunParams p = GetParam();
    TestCommon(p, 5, 0, 500);
}

INSTANTIATE_TEST_CASE_P(NxM, TestStagingMPMD,
                        ::testing::ValuesIn(CreateRunParams()));

//******************************************************************************
// main
//******************************************************************************

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    ::testing::InitGoogleTest(&argc, argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    engineName = std::string(argv[1]);

    if (!wrank)
    {
        std::cout << "Test " << engineName << " engine with " << numprocs
                  << " processes " << std::endl;
    }

    int result;
    result = RUN_ALL_TESTS();

    MPI_Finalize();
    return result;
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkMicrobirdTrackingDevice.h"

#include <itksys/SystemTools.hxx>
#include <itkMutexLockHolder.h>

typedef itk::MutexLockHolder<itk::FastMutexLock> MutexLockHolder;

mitk::MicroBirdTrackingDevice::MicroBirdTrackingDevice() : TrackingDevice(),
m_ErrorMessage(""),
m_ThreadID(0),
m_pl(50), // 50 Hz for Europe
m_metric(true),
m_agcModeBoth(true),
m_measurementRate(68.3), // 68.3 for mid-range transmitter, 40.5 for flat transmitter
m_TransmitterConfig(nullptr),
m_SensorConfig(nullptr)
{
  // Flat transmitter needs measurement rate: 40.5
  // Mid-range transmitter needs measurement rate: 68.3;

  // Set the tracker type
  this->m_Data = mitk::DeviceDataMicroBird;

  // Clear tools vector
  m_Tools.clear();

  // Create tools vector mutex
  m_ToolsMutex = itk::FastMutexLock::New();

  // Prepare multi-threading
  m_MultiThreader = itk::MultiThreader::New();

  // Pointer to record member variable
  pRecord = &record;
}

mitk::MicroBirdTrackingDevice::~MicroBirdTrackingDevice()
{
  if (m_MultiThreader)
    m_MultiThreader->TerminateThread(m_ThreadID);
  m_MultiThreader = nullptr;
  if (m_ToolsMutex)
    m_ToolsMutex->Unlock();
  m_ToolsMutex = nullptr;

  this->StopTracking();
  this->CloseConnection();

  if (m_TransmitterConfig != nullptr)
    delete [] m_TransmitterConfig;
  if (m_SensorConfig != nullptr)
    delete [] m_SensorConfig;

  //\TODO: Do we need to clean up the pointers to PCIBird data like DOUBLE_POSITION_QUATERNION_TIME_Q_RECORD?
}

bool mitk::MicroBirdTrackingDevice::OpenConnection()
{
  /* Check whether in setup mode */
  if (this->GetState() != Setup)
  {
    this->SetErrorMessage("Can only try to open the connection if in setup mode");
    return false;
  }

  int errorCode; // Holds error code

  /* Initialize the PCIBIRD driver and DLL */
  errorCode = InitializeBIRDSystem(); // this function can take a few seconds
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }
  /// @todo : check for transmitter serial numbers here?
  // Serial numbers could be compared to known ones for some simple
  //    parameters sanity check (measurement frequency etc.)

  /* Get system configuration */
  errorCode = GetBIRDSystemConfiguration(&m_SystemConfig);
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* use metric measurements in mm */
  errorCode = SetSystemParameter(METRIC, &m_metric, sizeof(m_metric));
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Set the measurement rate to m_measurementRate */
  if ((m_measurementRate > 30) && (m_measurementRate < 80))
  {
    errorCode = SetSystemParameter(MEASUREMENT_RATE, &m_measurementRate, sizeof(m_measurementRate));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
  }

  /* Set power line frequency */
  if ((m_pl >= 50) && (m_pl <= 60))
  {
    errorCode = SetSystemParameter(POWER_LINE_FREQUENCY, &m_pl, sizeof(m_pl));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
  }

  /* Set AGC mode */
  m_agc = m_agcModeBoth ? TRANSMITTER_AND_SENSOR_AGC : SENSOR_AGC_ONLY;
  errorCode = SetSystemParameter(AGC_MODE, &m_agc, sizeof(m_agc));
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Get system configuration */
  errorCode = GetBIRDSystemConfiguration(&m_SystemConfig);
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Get sensor information */
  m_SensorConfig = new SENSOR_CONFIGURATION[m_SystemConfig.numberSensors];
  for (int i = 0; i < m_SystemConfig.numberSensors; i++)
  {
    errorCode = GetSensorConfiguration(i, &(m_SensorConfig[i]));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }

    /* Initialize the quality parameter structure */
    QUALITY_PARAMETERS qualityParameters; // = { 164, 0, 32, 3072 };
    GetSensorParameter(i, QUALITY, &qualityParameters, sizeof(qualityParameters));

    /* Set data format to matrix format */
    //DATA_FORMAT_TYPE tempBuffer = DOUBLE_POSITION_MATRIX_TIME_Q;
    /* Set data format to quaternion format */
    DATA_FORMAT_TYPE tempBuffer = DOUBLE_POSITION_QUATERNION_TIME_Q;

    /* Set data format for sensor */
    DATA_FORMAT_TYPE *pTempBuffer = &tempBuffer;
    errorCode = SetSensorParameter(i, DATA_FORMAT, pTempBuffer, sizeof(tempBuffer));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }
  }

  /* Initialize tools vector */
  {
    MutexLockHolder(*m_ToolsMutex);
    for (int i = 0; i < m_SystemConfig.numberSensors; i++)
    {
      if (m_SensorConfig[i].attached)
        m_Tools.push_back(ToolType::New());

    }
  }

  /* Get transmitter configuration */
  m_TransmitterConfig = new TRANSMITTER_CONFIGURATION[m_SystemConfig.numberTransmitters];
  for (int i = 0; i < m_SystemConfig.numberTransmitters; i++)
  {
    errorCode = GetTransmitterConfiguration(i, &(m_TransmitterConfig[i]));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }
  }

  /* Switch off transmitter */
  SwitchTransmitter(true);
  SwitchTransmitter(false);

  // @todo : set up error scaling?

  /* finish  - now all tools should be added, initialized and enabled, so that tracking can be started */
  this->SetState(Ready);
  this->SetErrorMessage("");
  return true; // Return success
}

bool mitk::MicroBirdTrackingDevice::SwitchTransmitter(bool switchOn)
{
  if (switchOn)
  {
    /* Search for the first attached transmitter and turn it on */
    for (short id = 0; id < m_SystemConfig.numberTransmitters; id++)
    {
      if (m_TransmitterConfig[id].attached)
      {
        // Transmitter selection is a system function.
        // Using the SELECT_TRANSMITTER parameter we send the id of the
        // transmitter that we want to run with the SetSystemParameter() call
        int errorCode = SetSystemParameter(SELECT_TRANSMITTER, &id, sizeof(id));
        if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
        {
          HandleError(errorCode);
          return false;
        }
        else
          return true; //break; // \TODO: Stop after the first attached transmitter was turned off?
      }
    }
  }
  else
  {
    /* Transmitter selection is a system function, Note: a selector of -1 switches off the current transmitter */
    short TRANSMITTER_OFF = -1;
    int errorCode = SetSystemParameter(SELECT_TRANSMITTER, &TRANSMITTER_OFF, sizeof(TRANSMITTER_OFF));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
    else
      return true;
  }
  // Return success
  return true;
}

bool mitk::MicroBirdTrackingDevice::CloseConnection()
{
  SwitchTransmitter(false); // Switch off the transmitter

  int errorCode = CloseBIRDSystem(); // Close connection. This function can take a few seconds

  // Error checking
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    HandleError(errorCode);

  // Delete configuration
  if (m_TransmitterConfig != nullptr)
  {
    delete [] m_TransmitterConfig;
    m_TransmitterConfig = nullptr;
  }
  if (m_SensorConfig != nullptr)
  {
    delete [] m_SensorConfig;
    m_SensorConfig = nullptr;
  }
  // Change mode and release mutex
  this->SetState(Setup);

  // Clear error message
  this->SetErrorMessage("");

  return true;
}

ITK_THREAD_RETURN_TYPE mitk::MicroBirdTrackingDevice::ThreadStartTracking(void* pInfoStruct)
{
  /* extract this pointer from Thread Info structure */
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
  if ((pInfo == nullptr) || (pInfo->UserData == nullptr))
    return ITK_THREAD_RETURN_VALUE;

  MicroBirdTrackingDevice *trackingDevice = (MicroBirdTrackingDevice*)pInfo->UserData;
  if (trackingDevice != nullptr)
    trackingDevice->TrackTools();             // call TrackTools() from the original object

  return ITK_THREAD_RETURN_VALUE;
}

bool mitk::MicroBirdTrackingDevice::StopTracking()
{
  TrackingDevice::StopTracking(); // Call superclass method

  SwitchTransmitter(false); // Switch off transmitter
  InvalidateAll(); // Invalidate all tools
  return true;   // \todo : think about return value
}

bool mitk::MicroBirdTrackingDevice::StartTracking()
{
  if (this->GetState() != Ready)
    return false;

  this->SetState(Tracking);

  /* Switch on transmitter */
  SwitchTransmitter(true);

  /* Update the local copy of m_StopTracking */
  this->m_StopTrackingMutex->Lock();
  this->m_StopTracking = false;
  this->m_StopTrackingMutex->Unlock();

  m_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread
  m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
  mitk::TimeStamp::GetInstance()->Start(this);
  return true;
}

void mitk::MicroBirdTrackingDevice::TrackTools()
{
  if (this->GetState() != Tracking)
    return;

  /* Frequency configuration */
  double updateRate = 1000.0 / m_SystemConfig.measurementRate;
  double measurementDuration = 0.0;

  // lock the TrackingFinishedMutex to signal that the execution rights
  //   are now transfered to the tracking thread
  MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope

  // Because m_StopTracking is used by two threads, access has to be guarded
  //   by a mutex. To minimize thread locking, a local copy is used here
  bool localStopTracking;

  /* update the local copy of m_StopTracking */
  this->m_StopTrackingMutex->Lock();
  localStopTracking = this->m_StopTracking;
  this->m_StopTrackingMutex->Unlock();

  /* Tracking loop */
  while ((this->GetState() == Tracking) && (localStopTracking == false))
  {
    int errorCode;
    unsigned int nOfAttachedSensors = 0;
    double timeStamp = 0.0;
    int toolNumber = 0; // Numbers for attached sensors only

    for (int sensorID = 0; sensorID < m_SystemConfig.numberSensors; sensorID++) // for each sensor grep data
    {
      if (!m_SensorConfig[sensorID].attached)
        continue;

      // sensor attached so get record
      errorCode = GetAsynchronousRecord(sensorID, pRecord, sizeof(record));
      if (CompareError(errorCode, BIRD_ERROR_SUCCESS))
      { // On SUCCESS, parse sensor information
        nOfAttachedSensors++;
        timeStamp += record.time; // Get timestamp from record
        ToolType* tool = GetMicroBirdTool(toolNumber); /// Get tool (current sensor)
        if (tool != nullptr)
        {
          tool->SetTrackingError(record.quality); // Set tracking error (quality) from record
          mitk::Point3D position;
          position[0] = record.x;
          position[1] = record.y;
          position[2] = record.z;
          tool->SetPosition(position);  // Set position
          mitk::Quaternion orientation(record.q[1], record.q[2], record.q[3],record.q[0]);
          tool->SetOrientation(orientation); // Set orientation as quaternion \todo : verify quaternion order q(r,x,y,z)
          tool->SetDataValid(true); // Set data state to valid
        }
        toolNumber++; // Increment tool number
      }
      else
      { // ERROR while reading sensor information
        HandleError(errorCode);
      }
    }

    /// @todo : is there any synchronisation?
    // Average timestamp: timeStamp/nOfAttachedSensors

    // Compute sleep time
    double sleepTime = updateRate - measurementDuration;
    // Sleep
    if (sleepTime > 0.0 && sleepTime < 500.0)
    {
      // Note: we only have to approximately sleep one measurement cycle,
      //    since the tracker keeps track of the measurement rate itself
      itksys::SystemTools::Delay(sleepTime)
      //Sleep(static_cast<DWORD>(sleepTime));
    }

    // Update the local copy of m_StopTracking
    this->m_StopTrackingMutex->Lock();
    localStopTracking = m_StopTracking;
    this->m_StopTrackingMutex->Unlock();
  }

  // @bug (#1813) : maybe we need to check for localStopTracking=true here?
  //    m_StopTracking should only ever be updated by StopTracking(), so
  //    maybe we should not unlock a mutex that nobody is waiting for?

  return; // returning from this function (and ThreadStartTracking()) this will end the thread
}

mitk::TrackingTool* mitk::MicroBirdTrackingDevice::GetTool(unsigned int toolNumber)
{
  return static_cast<TrackingTool*>(GetMicroBirdTool(toolNumber));
}

mitk::MicroBirdTrackingDevice::ToolType* mitk::MicroBirdTrackingDevice::GetMicroBirdTool(unsigned int toolNumber)
{
  ToolType* t = nullptr;

  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  if (toolNumber < m_Tools.size())
  {
    t = m_Tools.at(toolNumber);
  }
  return t;
}

unsigned int mitk::MicroBirdTrackingDevice::GetToolCount() const
{
  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  return m_Tools.size();
}

bool mitk::MicroBirdTrackingDevice::CompareError(int errorCode, int errorConstant)
{
  return ((errorCode & 0xffff) == errorConstant);
}

void mitk::MicroBirdTrackingDevice::HandleError(int errorCode)
{
  char buffer[1024];
  char* pBuffer = &buffer[0];

  while(!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    // Print error number on screen
    //cout << "MicroBIRD Error Code: " << errorCode << endl;
    // Print error message on screen
    errorCode = GetErrorText(errorCode, pBuffer, sizeof(buffer), SIMPLE_MESSAGE);
    /// @todo : set error message, does it work?
    this->SetErrorMessage(buffer);
  }
}

void mitk::MicroBirdTrackingDevice::InvalidateAll()
{
  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  for (ToolContainerType::iterator iterator = m_Tools.begin(); iterator != m_Tools.end(); ++iterator)
    (*iterator)->SetDataValid(false);
}
<commit_msg>Use typedef consistently<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkMicrobirdTrackingDevice.h"

#include <itksys/SystemTools.hxx>
#include <itkMutexLockHolder.h>

typedef itk::MutexLockHolder<itk::FastMutexLock> MutexLockHolder;

mitk::MicroBirdTrackingDevice::MicroBirdTrackingDevice() : TrackingDevice(),
m_ErrorMessage(""),
m_ThreadID(0),
m_pl(50), // 50 Hz for Europe
m_metric(true),
m_agcModeBoth(true),
m_measurementRate(68.3), // 68.3 for mid-range transmitter, 40.5 for flat transmitter
m_TransmitterConfig(nullptr),
m_SensorConfig(nullptr)
{
  // Flat transmitter needs measurement rate: 40.5
  // Mid-range transmitter needs measurement rate: 68.3;

  // Set the tracker type
  this->m_Data = mitk::DeviceDataMicroBird;

  // Clear tools vector
  m_Tools.clear();

  // Create tools vector mutex
  m_ToolsMutex = itk::FastMutexLock::New();

  // Prepare multi-threading
  m_MultiThreader = itk::MultiThreader::New();

  // Pointer to record member variable
  pRecord = &record;
}

mitk::MicroBirdTrackingDevice::~MicroBirdTrackingDevice()
{
  if (m_MultiThreader)
    m_MultiThreader->TerminateThread(m_ThreadID);
  m_MultiThreader = nullptr;
  if (m_ToolsMutex)
    m_ToolsMutex->Unlock();
  m_ToolsMutex = nullptr;

  this->StopTracking();
  this->CloseConnection();

  if (m_TransmitterConfig != nullptr)
    delete [] m_TransmitterConfig;
  if (m_SensorConfig != nullptr)
    delete [] m_SensorConfig;

  //\TODO: Do we need to clean up the pointers to PCIBird data like DOUBLE_POSITION_QUATERNION_TIME_Q_RECORD?
}

bool mitk::MicroBirdTrackingDevice::OpenConnection()
{
  /* Check whether in setup mode */
  if (this->GetState() != Setup)
  {
    this->SetErrorMessage("Can only try to open the connection if in setup mode");
    return false;
  }

  int errorCode; // Holds error code

  /* Initialize the PCIBIRD driver and DLL */
  errorCode = InitializeBIRDSystem(); // this function can take a few seconds
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }
  /// @todo : check for transmitter serial numbers here?
  // Serial numbers could be compared to known ones for some simple
  //    parameters sanity check (measurement frequency etc.)

  /* Get system configuration */
  errorCode = GetBIRDSystemConfiguration(&m_SystemConfig);
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* use metric measurements in mm */
  errorCode = SetSystemParameter(METRIC, &m_metric, sizeof(m_metric));
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Set the measurement rate to m_measurementRate */
  if ((m_measurementRate > 30) && (m_measurementRate < 80))
  {
    errorCode = SetSystemParameter(MEASUREMENT_RATE, &m_measurementRate, sizeof(m_measurementRate));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
  }

  /* Set power line frequency */
  if ((m_pl >= 50) && (m_pl <= 60))
  {
    errorCode = SetSystemParameter(POWER_LINE_FREQUENCY, &m_pl, sizeof(m_pl));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
  }

  /* Set AGC mode */
  m_agc = m_agcModeBoth ? TRANSMITTER_AND_SENSOR_AGC : SENSOR_AGC_ONLY;
  errorCode = SetSystemParameter(AGC_MODE, &m_agc, sizeof(m_agc));
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Get system configuration */
  errorCode = GetBIRDSystemConfiguration(&m_SystemConfig);
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    HandleError(errorCode);
    return false;
  }

  /* Get sensor information */
  m_SensorConfig = new SENSOR_CONFIGURATION[m_SystemConfig.numberSensors];
  for (int i = 0; i < m_SystemConfig.numberSensors; i++)
  {
    errorCode = GetSensorConfiguration(i, &(m_SensorConfig[i]));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }

    /* Initialize the quality parameter structure */
    QUALITY_PARAMETERS qualityParameters; // = { 164, 0, 32, 3072 };
    GetSensorParameter(i, QUALITY, &qualityParameters, sizeof(qualityParameters));

    /* Set data format to matrix format */
    //DATA_FORMAT_TYPE tempBuffer = DOUBLE_POSITION_MATRIX_TIME_Q;
    /* Set data format to quaternion format */
    DATA_FORMAT_TYPE tempBuffer = DOUBLE_POSITION_QUATERNION_TIME_Q;

    /* Set data format for sensor */
    DATA_FORMAT_TYPE *pTempBuffer = &tempBuffer;
    errorCode = SetSensorParameter(i, DATA_FORMAT, pTempBuffer, sizeof(tempBuffer));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }
  }

  /* Initialize tools vector */
  {
    MutexLockHolder(*m_ToolsMutex);
    for (int i = 0; i < m_SystemConfig.numberSensors; i++)
    {
      if (m_SensorConfig[i].attached)
        m_Tools.push_back(ToolType::New());

    }
  }

  /* Get transmitter configuration */
  m_TransmitterConfig = new TRANSMITTER_CONFIGURATION[m_SystemConfig.numberTransmitters];
  for (int i = 0; i < m_SystemConfig.numberTransmitters; i++)
  {
    errorCode = GetTransmitterConfiguration(i, &(m_TransmitterConfig[i]));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
    }
  }

  /* Switch off transmitter */
  SwitchTransmitter(true);
  SwitchTransmitter(false);

  // @todo : set up error scaling?

  /* finish  - now all tools should be added, initialized and enabled, so that tracking can be started */
  this->SetState(Ready);
  this->SetErrorMessage("");
  return true; // Return success
}

bool mitk::MicroBirdTrackingDevice::SwitchTransmitter(bool switchOn)
{
  if (switchOn)
  {
    /* Search for the first attached transmitter and turn it on */
    for (short id = 0; id < m_SystemConfig.numberTransmitters; id++)
    {
      if (m_TransmitterConfig[id].attached)
      {
        // Transmitter selection is a system function.
        // Using the SELECT_TRANSMITTER parameter we send the id of the
        // transmitter that we want to run with the SetSystemParameter() call
        int errorCode = SetSystemParameter(SELECT_TRANSMITTER, &id, sizeof(id));
        if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
        {
          HandleError(errorCode);
          return false;
        }
        else
          return true; //break; // \TODO: Stop after the first attached transmitter was turned off?
      }
    }
  }
  else
  {
    /* Transmitter selection is a system function, Note: a selector of -1 switches off the current transmitter */
    short TRANSMITTER_OFF = -1;
    int errorCode = SetSystemParameter(SELECT_TRANSMITTER, &TRANSMITTER_OFF, sizeof(TRANSMITTER_OFF));
    if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    {
      HandleError(errorCode);
      return false;
    }
    else
      return true;
  }
  // Return success
  return true;
}

bool mitk::MicroBirdTrackingDevice::CloseConnection()
{
  SwitchTransmitter(false); // Switch off the transmitter

  int errorCode = CloseBIRDSystem(); // Close connection. This function can take a few seconds

  // Error checking
  if (!CompareError(errorCode, BIRD_ERROR_SUCCESS))
    HandleError(errorCode);

  // Delete configuration
  if (m_TransmitterConfig != nullptr)
  {
    delete [] m_TransmitterConfig;
    m_TransmitterConfig = nullptr;
  }
  if (m_SensorConfig != nullptr)
  {
    delete [] m_SensorConfig;
    m_SensorConfig = nullptr;
  }
  // Change mode and release mutex
  this->SetState(Setup);

  // Clear error message
  this->SetErrorMessage("");

  return true;
}

ITK_THREAD_RETURN_TYPE mitk::MicroBirdTrackingDevice::ThreadStartTracking(void* pInfoStruct)
{
  /* extract this pointer from Thread Info structure */
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
  if ((pInfo == nullptr) || (pInfo->UserData == nullptr))
    return ITK_THREAD_RETURN_VALUE;

  MicroBirdTrackingDevice *trackingDevice = (MicroBirdTrackingDevice*)pInfo->UserData;
  if (trackingDevice != nullptr)
    trackingDevice->TrackTools();             // call TrackTools() from the original object

  return ITK_THREAD_RETURN_VALUE;
}

bool mitk::MicroBirdTrackingDevice::StopTracking()
{
  TrackingDevice::StopTracking(); // Call superclass method

  SwitchTransmitter(false); // Switch off transmitter
  InvalidateAll(); // Invalidate all tools
  return true;   // \todo : think about return value
}

bool mitk::MicroBirdTrackingDevice::StartTracking()
{
  if (this->GetState() != Ready)
    return false;

  this->SetState(Tracking);

  /* Switch on transmitter */
  SwitchTransmitter(true);

  /* Update the local copy of m_StopTracking */
  this->m_StopTrackingMutex->Lock();
  this->m_StopTracking = false;
  this->m_StopTrackingMutex->Unlock();

  m_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread
  m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
  mitk::TimeStamp::GetInstance()->Start(this);
  return true;
}

void mitk::MicroBirdTrackingDevice::TrackTools()
{
  if (this->GetState() != Tracking)
    return;

  /* Frequency configuration */
  double updateRate = 1000.0 / m_SystemConfig.measurementRate;
  double measurementDuration = 0.0;

  // lock the TrackingFinishedMutex to signal that the execution rights
  //   are now transfered to the tracking thread
  MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope

  // Because m_StopTracking is used by two threads, access has to be guarded
  //   by a mutex. To minimize thread locking, a local copy is used here
  bool localStopTracking;

  /* update the local copy of m_StopTracking */
  this->m_StopTrackingMutex->Lock();
  localStopTracking = this->m_StopTracking;
  this->m_StopTrackingMutex->Unlock();

  /* Tracking loop */
  while ((this->GetState() == Tracking) && (localStopTracking == false))
  {
    int errorCode;
    unsigned int nOfAttachedSensors = 0;
    double timeStamp = 0.0;
    int toolNumber = 0; // Numbers for attached sensors only

    for (int sensorID = 0; sensorID < m_SystemConfig.numberSensors; sensorID++) // for each sensor grep data
    {
      if (!m_SensorConfig[sensorID].attached)
        continue;

      // sensor attached so get record
      errorCode = GetAsynchronousRecord(sensorID, pRecord, sizeof(record));
      if (CompareError(errorCode, BIRD_ERROR_SUCCESS))
      { // On SUCCESS, parse sensor information
        nOfAttachedSensors++;
        timeStamp += record.time; // Get timestamp from record
        ToolType* tool = GetMicroBirdTool(toolNumber); /// Get tool (current sensor)
        if (tool != nullptr)
        {
          tool->SetTrackingError(record.quality); // Set tracking error (quality) from record
          mitk::Point3D position;
          position[0] = record.x;
          position[1] = record.y;
          position[2] = record.z;
          tool->SetPosition(position);  // Set position
          mitk::Quaternion orientation(record.q[1], record.q[2], record.q[3],record.q[0]);
          tool->SetOrientation(orientation); // Set orientation as quaternion \todo : verify quaternion order q(r,x,y,z)
          tool->SetDataValid(true); // Set data state to valid
        }
        toolNumber++; // Increment tool number
      }
      else
      { // ERROR while reading sensor information
        HandleError(errorCode);
      }
    }

    /// @todo : is there any synchronisation?
    // Average timestamp: timeStamp/nOfAttachedSensors

    // Compute sleep time
    double sleepTime = updateRate - measurementDuration;
    // Sleep
    if (sleepTime > 0.0 && sleepTime < 500.0)
    {
      // Note: we only have to approximately sleep one measurement cycle,
      //    since the tracker keeps track of the measurement rate itself
      itksys::SystemTools::Delay(sleepTime)
      //Sleep(static_cast<DWORD>(sleepTime));
    }

    // Update the local copy of m_StopTracking
    this->m_StopTrackingMutex->Lock();
    localStopTracking = m_StopTracking;
    this->m_StopTrackingMutex->Unlock();
  }

  // @bug (#1813) : maybe we need to check for localStopTracking=true here?
  //    m_StopTracking should only ever be updated by StopTracking(), so
  //    maybe we should not unlock a mutex that nobody is waiting for?

  return; // returning from this function (and ThreadStartTracking()) this will end the thread
}

mitk::ToolType* mitk::MicroBirdTrackingDevice::GetTool(unsigned int toolNumber)
{
  return static_cast<ToolType*>(GetMicroBirdTool(toolNumber));
}

mitk::MicroBirdTrackingDevice::ToolType* mitk::MicroBirdTrackingDevice::GetMicroBirdTool(unsigned int toolNumber)
{
  ToolType* t = nullptr;

  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  if (toolNumber < m_Tools.size())
  {
    t = m_Tools.at(toolNumber);
  }
  return t;
}

unsigned int mitk::MicroBirdTrackingDevice::GetToolCount() const
{
  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  return m_Tools.size();
}

bool mitk::MicroBirdTrackingDevice::CompareError(int errorCode, int errorConstant)
{
  return ((errorCode & 0xffff) == errorConstant);
}

void mitk::MicroBirdTrackingDevice::HandleError(int errorCode)
{
  char buffer[1024];
  char* pBuffer = &buffer[0];

  while(!CompareError(errorCode, BIRD_ERROR_SUCCESS))
  {
    // Print error number on screen
    //cout << "MicroBIRD Error Code: " << errorCode << endl;
    // Print error message on screen
    errorCode = GetErrorText(errorCode, pBuffer, sizeof(buffer), SIMPLE_MESSAGE);
    /// @todo : set error message, does it work?
    this->SetErrorMessage(buffer);
  }
}

void mitk::MicroBirdTrackingDevice::InvalidateAll()
{
  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
  for (ToolContainerType::iterator iterator = m_Tools.begin(); iterator != m_Tools.end(); ++iterator)
    (*iterator)->SetDataValid(false);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: smplmailclient.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: vg $ $Date: 2007-03-26 13:52:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_shell.hxx"

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

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

#ifndef _OSL_MODULE_HXX_
#include <osl/module.hxx>
#endif

#ifndef _SMPLMAILCLIENT_HXX_
#include "smplmailclient.hxx"
#endif

#ifndef _SMPLMAILMSG_HXX_
#include "smplmailmsg.hxx"
#endif

#ifndef _COM_SUN_STAR_SYSTEM_SIMPLEMAILCLIENTFLAGS_HPP_
#include <com/sun/star/system/SimpleMailClientFlags.hpp>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif

#define WIN32_LEAN_AND_MEAN
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include <mapi.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

#include <process.h>
#include <vector>

using css::uno::Reference;
using css::uno::Exception;
using css::uno::RuntimeException;
using css::uno::Sequence;
using css::lang::IllegalArgumentException;

using css::system::XSimpleMailClient;
using css::system::XSimpleMailMessage;
using css::system::SimpleMailClientFlags::NO_USER_INTERFACE;
using css::system::SimpleMailClientFlags::NO_LOGON_DIALOG;

typedef std::vector<rtl::OUString> StringList_t;
typedef StringList_t::const_iterator StringListIterator_t;

const rtl::OUString TO = rtl::OUString::createFromAscii("--to");
const rtl::OUString CC = rtl::OUString::createFromAscii("--cc");
const rtl::OUString BCC = rtl::OUString::createFromAscii("--bcc");
const rtl::OUString FROM = rtl::OUString::createFromAscii("--from");
const rtl::OUString SUBJECT = rtl::OUString::createFromAscii("--subject");
const rtl::OUString BODY = rtl::OUString::createFromAscii("--body");
const rtl::OUString ATTACH = rtl::OUString::createFromAscii("--attach");
const rtl::OUString FLAG_MAPI_DIALOG = rtl::OUString::createFromAscii("--mapi-dialog");
const rtl::OUString FLAG_MAPI_LOGON_UI = rtl::OUString::createFromAscii("--mapi-logon-ui");

namespace /* private */
{
    /** @internal
        look if an alternative program is configured
        which should be used as senddoc executable */
    rtl::OUString getAlternativeSenddocUrl()
    {
        rtl::OUString altSenddocUrl;
        HKEY hkey;
        LONG lret = RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\OpenOffice.org\\SendAsEMailClient", &hkey);
        if (lret == ERROR_SUCCESS)
        {
            wchar_t buff[MAX_PATH];
            LONG sz = sizeof(buff);
            lret = RegQueryValueW(hkey, NULL, buff, &sz);
            if (lret == ERROR_SUCCESS)
            {
                osl::FileBase::getFileURLFromSystemPath(reinterpret_cast<const sal_Unicode*>(buff), altSenddocUrl);
            }
            RegCloseKey(hkey);
        }
        return altSenddocUrl;
    }

    /**
        Returns the absolute file Url of the senddoc executable.

        @returns
        the absolute file Url of the senddoc executable. In case
        of an error an empty string will be returned.
    */
    rtl::OUString getSenddocUrl()
    {
        rtl::OUString senddocUrl = getAlternativeSenddocUrl();

        if (senddocUrl.getLength() == 0)
        {
            rtl::OUString baseUrl;
            if (!osl::Module::getUrlFromAddress(reinterpret_cast<oslGenericFunction>(getSenddocUrl), baseUrl))
                return rtl::OUString();

            senddocUrl = baseUrl.copy(0, baseUrl.lastIndexOf('/') + 1);
            senddocUrl += rtl::OUString::createFromAscii("senddoc.exe");
        }
        return senddocUrl;
    }

    /**
        Execute Senddoc.exe which a MAPI wrapper.

        @param rCommandArgs
        [in] the arguments to be passed to Senddoc.exe

        @returns
        <TRUE/> on success.
    */
    bool executeSenddoc(const StringList_t& rCommandArgs)
    {
        rtl::OUString senddocUrl = getSenddocUrl();
        if (senddocUrl.getLength() == 0)
            return false;

        oslProcess proc;
        oslProcessError err = osl_Process_E_Unknown;

        /* for efficiency reasons we are using a 'bad' cast here
        as a vector or rtl::OUStrings is nothing else than
        an array of pointers to rtl_uString's */
        err = osl_executeProcess(
            senddocUrl.pData,
            (rtl_uString**)&rCommandArgs[0],
            rCommandArgs.size(),
            osl_Process_WAIT | osl_Process_DETACHED,
            NULL,
            NULL,
            NULL,
            0,
            &proc);

        if (err != osl_Process_E_None)
            return false;

        oslProcessInfo procInfo;
        procInfo.Size = sizeof(oslProcessInfo);
        osl_getProcessInfo(proc, osl_Process_EXITCODE, &procInfo);
        osl_freeProcessHandle(proc);
        return (procInfo.Code == SUCCESS_SUCCESS);
    }
} // namespace private

Reference<XSimpleMailMessage> SAL_CALL CSmplMailClient::createSimpleMailMessage()
    throw (RuntimeException)
{
    return Reference<XSimpleMailMessage>(new CSmplMailMsg());
}

/**
    Assemble a command line for SendDoc.exe out of the members
    of the supplied SimpleMailMessage.

    @param xSimpleMailMessage
    [in] the mail message.

    @param aFlags
    [in] different flags to be used with the simple mail service.

    @param rCommandArgs
    [in|out] a buffer for the command line arguments. The buffer
    is assumed to be empty.

    @throws com::sun::star::lang::IllegalArgumentException
    if an invalid file URL has been detected in the attachment list.
*/
void CSmplMailClient::assembleCommandLine(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage,
    sal_Int32 aFlag, StringList_t& rCommandArgs)
{
    OSL_ENSURE(rCommandArgs.size() == 0, "Provided command argument buffer not empty");

    rtl::OUString to = xSimpleMailMessage->getRecipient();
    if (to.getLength() > 0)
    {
        rCommandArgs.push_back(TO);
        rCommandArgs.push_back(to);
    }

    Sequence<rtl::OUString> ccRecipients = xSimpleMailMessage->getCcRecipient();
    for (int i = 0; i < ccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(CC);
        rCommandArgs.push_back(ccRecipients[i]);
    }

    Sequence<rtl::OUString> bccRecipients = xSimpleMailMessage->getBccRecipient();
    for (int i = 0; i < bccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(BCC);
        rCommandArgs.push_back(bccRecipients[i]);
    }

    rtl::OUString from = xSimpleMailMessage->getOriginator();
    if (from.getLength() > 0)
    {
        rCommandArgs.push_back(FROM);
        rCommandArgs.push_back(from);
    }

    rtl::OUString subject = xSimpleMailMessage->getSubject();
    if (subject.getLength() > 0)
    {
        rCommandArgs.push_back(SUBJECT);
        rCommandArgs.push_back(subject);
    }

    Sequence<rtl::OUString> attachments = xSimpleMailMessage->getAttachement();
    for (int i = 0; i < attachments.getLength(); i++)
    {
        rtl::OUString sysPath;
        osl::FileBase::RC err = osl::FileBase::getSystemPathFromFileURL(attachments[i], sysPath);
        if (err != osl::FileBase::E_None)
            throw IllegalArgumentException(
                rtl::OUString::createFromAscii("Invalid attachment file URL"),
                static_cast<XSimpleMailClient*>(this),
                1);

        rCommandArgs.push_back(ATTACH);
        rCommandArgs.push_back(sysPath);
    }

    if (!(aFlag & NO_USER_INTERFACE))
        rCommandArgs.push_back(FLAG_MAPI_DIALOG);

    if (!(aFlag & NO_LOGON_DIALOG))
        rCommandArgs.push_back(FLAG_MAPI_LOGON_UI);
}

void SAL_CALL CSmplMailClient::sendSimpleMailMessage(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag)
    throw (IllegalArgumentException, Exception, RuntimeException)
{
    validateParameter(xSimpleMailMessage, aFlag);

    StringList_t senddocParams;
    assembleCommandLine(xSimpleMailMessage, aFlag, senddocParams);

    if (!executeSenddoc(senddocParams))
        throw Exception(
            rtl::OUString::createFromAscii("Send email failed"),
            static_cast<XSimpleMailClient*>(this));
}

void CSmplMailClient::validateParameter(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag )
{
    if (!xSimpleMailMessage.is())
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("Empty mail message reference"),
            static_cast<XSimpleMailClient*>(this),
            1);

    // #93077#
    OSL_ENSURE(!(aFlag & NO_LOGON_DIALOG), "Flag NO_LOGON_DIALOG has currently no effect");

    // check the flags, the allowed range is 0 - (2^n - 1)
    if (aFlag < 0 || aFlag > 3)
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("Invalid flag value"),
            static_cast<XSimpleMailClient*>(this),
            2);

    // check if a recipient is specified of the flags NO_USER_INTERFACE is specified
    if ((aFlag & NO_USER_INTERFACE) && !xSimpleMailMessage->getRecipient().getLength())
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("No recipient specified"),
            static_cast<XSimpleMailClient*>(this),
            1);
}
<commit_msg>INTEGRATION: CWS changefileheader (1.15.82); FILE MERGED 2008/04/01 15:40:25 thb 1.15.82.3: #i85898# Stripping all external header guards 2008/04/01 12:41:17 thb 1.15.82.2: #i85898# Stripping all external header guards 2008/03/31 13:17:14 rt 1.15.82.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: smplmailclient.cxx,v $
 * $Revision: 1.16 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_shell.hxx"
#include <osl/diagnose.h>
#include <osl/process.h>
#include <osl/module.hxx>
#include "smplmailclient.hxx"
#include "smplmailmsg.hxx"
#include <com/sun/star/system/SimpleMailClientFlags.hpp>
#include <osl/file.hxx>

#define WIN32_LEAN_AND_MEAN
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include <mapi.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

#include <process.h>
#include <vector>

using css::uno::Reference;
using css::uno::Exception;
using css::uno::RuntimeException;
using css::uno::Sequence;
using css::lang::IllegalArgumentException;

using css::system::XSimpleMailClient;
using css::system::XSimpleMailMessage;
using css::system::SimpleMailClientFlags::NO_USER_INTERFACE;
using css::system::SimpleMailClientFlags::NO_LOGON_DIALOG;

typedef std::vector<rtl::OUString> StringList_t;
typedef StringList_t::const_iterator StringListIterator_t;

const rtl::OUString TO = rtl::OUString::createFromAscii("--to");
const rtl::OUString CC = rtl::OUString::createFromAscii("--cc");
const rtl::OUString BCC = rtl::OUString::createFromAscii("--bcc");
const rtl::OUString FROM = rtl::OUString::createFromAscii("--from");
const rtl::OUString SUBJECT = rtl::OUString::createFromAscii("--subject");
const rtl::OUString BODY = rtl::OUString::createFromAscii("--body");
const rtl::OUString ATTACH = rtl::OUString::createFromAscii("--attach");
const rtl::OUString FLAG_MAPI_DIALOG = rtl::OUString::createFromAscii("--mapi-dialog");
const rtl::OUString FLAG_MAPI_LOGON_UI = rtl::OUString::createFromAscii("--mapi-logon-ui");

namespace /* private */
{
    /** @internal
        look if an alternative program is configured
        which should be used as senddoc executable */
    rtl::OUString getAlternativeSenddocUrl()
    {
        rtl::OUString altSenddocUrl;
        HKEY hkey;
        LONG lret = RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\OpenOffice.org\\SendAsEMailClient", &hkey);
        if (lret == ERROR_SUCCESS)
        {
            wchar_t buff[MAX_PATH];
            LONG sz = sizeof(buff);
            lret = RegQueryValueW(hkey, NULL, buff, &sz);
            if (lret == ERROR_SUCCESS)
            {
                osl::FileBase::getFileURLFromSystemPath(reinterpret_cast<const sal_Unicode*>(buff), altSenddocUrl);
            }
            RegCloseKey(hkey);
        }
        return altSenddocUrl;
    }

    /**
        Returns the absolute file Url of the senddoc executable.

        @returns
        the absolute file Url of the senddoc executable. In case
        of an error an empty string will be returned.
    */
    rtl::OUString getSenddocUrl()
    {
        rtl::OUString senddocUrl = getAlternativeSenddocUrl();

        if (senddocUrl.getLength() == 0)
        {
            rtl::OUString baseUrl;
            if (!osl::Module::getUrlFromAddress(reinterpret_cast<oslGenericFunction>(getSenddocUrl), baseUrl))
                return rtl::OUString();

            senddocUrl = baseUrl.copy(0, baseUrl.lastIndexOf('/') + 1);
            senddocUrl += rtl::OUString::createFromAscii("senddoc.exe");
        }
        return senddocUrl;
    }

    /**
        Execute Senddoc.exe which a MAPI wrapper.

        @param rCommandArgs
        [in] the arguments to be passed to Senddoc.exe

        @returns
        <TRUE/> on success.
    */
    bool executeSenddoc(const StringList_t& rCommandArgs)
    {
        rtl::OUString senddocUrl = getSenddocUrl();
        if (senddocUrl.getLength() == 0)
            return false;

        oslProcess proc;
        oslProcessError err = osl_Process_E_Unknown;

        /* for efficiency reasons we are using a 'bad' cast here
        as a vector or rtl::OUStrings is nothing else than
        an array of pointers to rtl_uString's */
        err = osl_executeProcess(
            senddocUrl.pData,
            (rtl_uString**)&rCommandArgs[0],
            rCommandArgs.size(),
            osl_Process_WAIT | osl_Process_DETACHED,
            NULL,
            NULL,
            NULL,
            0,
            &proc);

        if (err != osl_Process_E_None)
            return false;

        oslProcessInfo procInfo;
        procInfo.Size = sizeof(oslProcessInfo);
        osl_getProcessInfo(proc, osl_Process_EXITCODE, &procInfo);
        osl_freeProcessHandle(proc);
        return (procInfo.Code == SUCCESS_SUCCESS);
    }
} // namespace private

Reference<XSimpleMailMessage> SAL_CALL CSmplMailClient::createSimpleMailMessage()
    throw (RuntimeException)
{
    return Reference<XSimpleMailMessage>(new CSmplMailMsg());
}

/**
    Assemble a command line for SendDoc.exe out of the members
    of the supplied SimpleMailMessage.

    @param xSimpleMailMessage
    [in] the mail message.

    @param aFlags
    [in] different flags to be used with the simple mail service.

    @param rCommandArgs
    [in|out] a buffer for the command line arguments. The buffer
    is assumed to be empty.

    @throws com::sun::star::lang::IllegalArgumentException
    if an invalid file URL has been detected in the attachment list.
*/
void CSmplMailClient::assembleCommandLine(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage,
    sal_Int32 aFlag, StringList_t& rCommandArgs)
{
    OSL_ENSURE(rCommandArgs.size() == 0, "Provided command argument buffer not empty");

    rtl::OUString to = xSimpleMailMessage->getRecipient();
    if (to.getLength() > 0)
    {
        rCommandArgs.push_back(TO);
        rCommandArgs.push_back(to);
    }

    Sequence<rtl::OUString> ccRecipients = xSimpleMailMessage->getCcRecipient();
    for (int i = 0; i < ccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(CC);
        rCommandArgs.push_back(ccRecipients[i]);
    }

    Sequence<rtl::OUString> bccRecipients = xSimpleMailMessage->getBccRecipient();
    for (int i = 0; i < bccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(BCC);
        rCommandArgs.push_back(bccRecipients[i]);
    }

    rtl::OUString from = xSimpleMailMessage->getOriginator();
    if (from.getLength() > 0)
    {
        rCommandArgs.push_back(FROM);
        rCommandArgs.push_back(from);
    }

    rtl::OUString subject = xSimpleMailMessage->getSubject();
    if (subject.getLength() > 0)
    {
        rCommandArgs.push_back(SUBJECT);
        rCommandArgs.push_back(subject);
    }

    Sequence<rtl::OUString> attachments = xSimpleMailMessage->getAttachement();
    for (int i = 0; i < attachments.getLength(); i++)
    {
        rtl::OUString sysPath;
        osl::FileBase::RC err = osl::FileBase::getSystemPathFromFileURL(attachments[i], sysPath);
        if (err != osl::FileBase::E_None)
            throw IllegalArgumentException(
                rtl::OUString::createFromAscii("Invalid attachment file URL"),
                static_cast<XSimpleMailClient*>(this),
                1);

        rCommandArgs.push_back(ATTACH);
        rCommandArgs.push_back(sysPath);
    }

    if (!(aFlag & NO_USER_INTERFACE))
        rCommandArgs.push_back(FLAG_MAPI_DIALOG);

    if (!(aFlag & NO_LOGON_DIALOG))
        rCommandArgs.push_back(FLAG_MAPI_LOGON_UI);
}

void SAL_CALL CSmplMailClient::sendSimpleMailMessage(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag)
    throw (IllegalArgumentException, Exception, RuntimeException)
{
    validateParameter(xSimpleMailMessage, aFlag);

    StringList_t senddocParams;
    assembleCommandLine(xSimpleMailMessage, aFlag, senddocParams);

    if (!executeSenddoc(senddocParams))
        throw Exception(
            rtl::OUString::createFromAscii("Send email failed"),
            static_cast<XSimpleMailClient*>(this));
}

void CSmplMailClient::validateParameter(
    const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag )
{
    if (!xSimpleMailMessage.is())
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("Empty mail message reference"),
            static_cast<XSimpleMailClient*>(this),
            1);

    // #93077#
    OSL_ENSURE(!(aFlag & NO_LOGON_DIALOG), "Flag NO_LOGON_DIALOG has currently no effect");

    // check the flags, the allowed range is 0 - (2^n - 1)
    if (aFlag < 0 || aFlag > 3)
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("Invalid flag value"),
            static_cast<XSimpleMailClient*>(this),
            2);

    // check if a recipient is specified of the flags NO_USER_INTERFACE is specified
    if ((aFlag & NO_USER_INTERFACE) && !xSimpleMailMessage->getRecipient().getLength())
        throw IllegalArgumentException(
            rtl::OUString::createFromAscii("No recipient specified"),
            static_cast<XSimpleMailClient*>(this),
            1);
}
<|endoftext|>


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

#include "apps/app_restore_service.h"
#include "apps/app_restore_service_factory.h"
#include "apps/saved_files_service.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_utils.h"

using extensions::Extension;
using extensions::ExtensionPrefs;
using extensions::ExtensionSystem;
using extensions::FileSystemChooseEntryFunction;

// TODO(benwells): Move PlatformAppBrowserTest to apps namespace in apps
// component.
using extensions::PlatformAppBrowserTest;

namespace apps {

// Tests that a running app is recorded in the preferences as such.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, RunningAppsAreRecorded) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  const Extension* extension = LoadExtension(
      test_data_dir_.AppendASCII("platform_apps/restart_test"));
  ASSERT_TRUE(extension);
  ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile());

  // App is running.
  ASSERT_TRUE(extension_prefs->IsExtensionRunning(extension->id()));

  // Wait for the extension to get suspended.
  extension_suspended.Wait();

  // App isn't running because it got suspended.
  ASSERT_FALSE(extension_prefs->IsExtensionRunning(extension->id()));

  // Pretend that the app is supposed to be running.
  extension_prefs->SetExtensionRunning(extension->id(), true);

  ExtensionTestMessageListener restart_listener("onRestarted", false);
  apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())->
      HandleStartup(true);
  restart_listener.WaitUntilSatisfied();
}

IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, FileAccessIsSavedToPrefs) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  base::ScopedTempDir temp_directory;
  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
  base::FilePath temp_file;
  ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_directory.path(),
                                                  &temp_file));

  FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
      &temp_file);
  FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
      "temp", temp_directory.path());

  ExtensionTestMessageListener file_written_listener("fileWritten", false);
  ExtensionTestMessageListener access_ok_listener(
      "restartedFileAccessOK", false);

  const Extension* extension =
      LoadAndLaunchPlatformApp("file_access_saved_to_prefs_test");
  ASSERT_TRUE(extension);
  file_written_listener.WaitUntilSatisfied();

  SavedFilesService* saved_files_service = SavedFilesService::Get(profile());

  std::vector<SavedFileEntry> file_entries =
      saved_files_service->GetAllFileEntries(extension->id());
  // One for the read-only file entry and one for the writable file entry.
  ASSERT_EQ(2u, file_entries.size());

  extension_suspended.Wait();
  file_entries = saved_files_service->GetAllFileEntries(extension->id());
  // File entries should be cleared when the extension is suspended.
  ASSERT_TRUE(file_entries.empty());
}

// Flaky: crbug.com/269613
#if defined(OS_LINUX)
#define MAYBE_FileAccessIsRestored DISABLED_FileAccessIsRestored
#else
#define MAYBE_FileAccessIsRestored FileAccessIsRestored
#endif

IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_FileAccessIsRestored) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  base::ScopedTempDir temp_directory;
  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
  base::FilePath temp_file;
  ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_directory.path(),
                                                  &temp_file));

  FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
      &temp_file);
  FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
      "temp", temp_directory.path());

  ExtensionTestMessageListener file_written_listener("fileWritten", false);
  ExtensionTestMessageListener access_ok_listener(
      "restartedFileAccessOK", false);

  const Extension* extension =
      LoadAndLaunchPlatformApp("file_access_restored_test");
  ASSERT_TRUE(extension);
  file_written_listener.WaitUntilSatisfied();

  ExtensionPrefs* extension_prefs =
      ExtensionPrefs::Get(browser()->profile());
  SavedFilesService* saved_files_service = SavedFilesService::Get(profile());
  std::vector<SavedFileEntry> file_entries =
      saved_files_service->GetAllFileEntries(extension->id());
  extension_suspended.Wait();

  // Simulate a restart by populating the preferences as if the browser didn't
  // get time to clean itself up.
  extension_prefs->SetExtensionRunning(extension->id(), true);
  for (std::vector<SavedFileEntry>::const_iterator it = file_entries.begin();
       it != file_entries.end(); ++it) {
    saved_files_service->RegisterFileEntry(
        extension->id(), it->id, it->path, it->is_directory);
  }

  apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())->
      HandleStartup(true);

  access_ok_listener.WaitUntilSatisfied();
}

}  // namespace apps
<commit_msg>Suppress flaky PlatformAppBrowserTest.FileAccesssIsRestored on win<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "apps/app_restore_service.h"
#include "apps/app_restore_service_factory.h"
#include "apps/saved_files_service.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_utils.h"

using extensions::Extension;
using extensions::ExtensionPrefs;
using extensions::ExtensionSystem;
using extensions::FileSystemChooseEntryFunction;

// TODO(benwells): Move PlatformAppBrowserTest to apps namespace in apps
// component.
using extensions::PlatformAppBrowserTest;

namespace apps {

// Tests that a running app is recorded in the preferences as such.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, RunningAppsAreRecorded) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  const Extension* extension = LoadExtension(
      test_data_dir_.AppendASCII("platform_apps/restart_test"));
  ASSERT_TRUE(extension);
  ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile());

  // App is running.
  ASSERT_TRUE(extension_prefs->IsExtensionRunning(extension->id()));

  // Wait for the extension to get suspended.
  extension_suspended.Wait();

  // App isn't running because it got suspended.
  ASSERT_FALSE(extension_prefs->IsExtensionRunning(extension->id()));

  // Pretend that the app is supposed to be running.
  extension_prefs->SetExtensionRunning(extension->id(), true);

  ExtensionTestMessageListener restart_listener("onRestarted", false);
  apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())->
      HandleStartup(true);
  restart_listener.WaitUntilSatisfied();
}

IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, FileAccessIsSavedToPrefs) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  base::ScopedTempDir temp_directory;
  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
  base::FilePath temp_file;
  ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_directory.path(),
                                                  &temp_file));

  FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
      &temp_file);
  FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
      "temp", temp_directory.path());

  ExtensionTestMessageListener file_written_listener("fileWritten", false);
  ExtensionTestMessageListener access_ok_listener(
      "restartedFileAccessOK", false);

  const Extension* extension =
      LoadAndLaunchPlatformApp("file_access_saved_to_prefs_test");
  ASSERT_TRUE(extension);
  file_written_listener.WaitUntilSatisfied();

  SavedFilesService* saved_files_service = SavedFilesService::Get(profile());

  std::vector<SavedFileEntry> file_entries =
      saved_files_service->GetAllFileEntries(extension->id());
  // One for the read-only file entry and one for the writable file entry.
  ASSERT_EQ(2u, file_entries.size());

  extension_suspended.Wait();
  file_entries = saved_files_service->GetAllFileEntries(extension->id());
  // File entries should be cleared when the extension is suspended.
  ASSERT_TRUE(file_entries.empty());
}

// Flaky: crbug.com/269613
#if defined(OS_LINUX) || defined(OS_WIN)
#define MAYBE_FileAccessIsRestored DISABLED_FileAccessIsRestored
#else
#define MAYBE_FileAccessIsRestored FileAccessIsRestored
#endif

IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_FileAccessIsRestored) {
  content::WindowedNotificationObserver extension_suspended(
      chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
      content::NotificationService::AllSources());

  base::ScopedTempDir temp_directory;
  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
  base::FilePath temp_file;
  ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_directory.path(),
                                                  &temp_file));

  FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
      &temp_file);
  FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
      "temp", temp_directory.path());

  ExtensionTestMessageListener file_written_listener("fileWritten", false);
  ExtensionTestMessageListener access_ok_listener(
      "restartedFileAccessOK", false);

  const Extension* extension =
      LoadAndLaunchPlatformApp("file_access_restored_test");
  ASSERT_TRUE(extension);
  file_written_listener.WaitUntilSatisfied();

  ExtensionPrefs* extension_prefs =
      ExtensionPrefs::Get(browser()->profile());
  SavedFilesService* saved_files_service = SavedFilesService::Get(profile());
  std::vector<SavedFileEntry> file_entries =
      saved_files_service->GetAllFileEntries(extension->id());
  extension_suspended.Wait();

  // Simulate a restart by populating the preferences as if the browser didn't
  // get time to clean itself up.
  extension_prefs->SetExtensionRunning(extension->id(), true);
  for (std::vector<SavedFileEntry>::const_iterator it = file_entries.begin();
       it != file_entries.end(); ++it) {
    saved_files_service->RegisterFileEntry(
        extension->id(), it->id, it->path, it->is_directory);
  }

  apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())->
      HandleStartup(true);

  access_ok_listener.WaitUntilSatisfied();
}

}  // namespace apps
<|endoftext|>


<commit_before>
#include "DriftPrivatePCH.h"

#include "PlatformName.h"

namespace details
{

const TCHAR* GetPlatformName()
{
    static const TCHAR platform_name[] =
#if PLATFORM_WINDOWS
    L"Windows";
#elif PLATFORM_PS4
    L"PS4";
#elif PLATFORM_XBOXONE
    L"XBOX1";
#elif PLATFORM_MAC
    L"MAC";
#elif PLATFORM_IOS
    return FIOSPlatformMisc::GetDefaultDeviceProfileName();
#elif PLATFORM_ANDROID
    L"Android";
#elif PLATFORM_WINRT_ARM
    L"WinRT";
#elif PLATFORM_WINRT
    L"WinRT";
#elif PLATFORM_HTML5
    L"HTML5";
#elif PLATFORM_LINUX
    L"Linux";
#else
#error Unknown Platform
#endif
    return platform_name;
}

} // namespace details
<commit_msg>Fix iOS build error<commit_after>
#include "DriftPrivatePCH.h"

#include "PlatformMisc.h"
#include "PlatformName.h"

namespace details
{

const TCHAR* GetPlatformName()
{
    static const TCHAR platform_name[] =
#if PLATFORM_WINDOWS
    L"Windows";
#elif PLATFORM_PS4
    L"PS4";
#elif PLATFORM_XBOXONE
    L"XBOX1";
#elif PLATFORM_MAC
    L"MAC";
#elif PLATFORM_IOS
    FIOSPlatformMisc::GetDefaultDeviceProfileName();
#elif PLATFORM_ANDROID
    L"Android";
#elif PLATFORM_WINRT_ARM
    L"WinRT";
#elif PLATFORM_WINRT
    L"WinRT";
#elif PLATFORM_HTML5
    L"HTML5";
#elif PLATFORM_LINUX
    L"Linux";
#else
#error Unknown Platform
#endif
    return platform_name;
}

} // namespace details
<|endoftext|>