<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTILS_HPP
#define MAPNIK_UTILS_HPP

#include <mapnik/config.hpp>

// stl
#include <stdexcept> // std::runtime_error
#include <cstdlib> // std::atexit
#include <new> // operator new

#ifdef MAPNIK_THREADSAFE
#include <mutex>
#endif

namespace mapnik
{

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }
    static void destroy(volatile T* obj)
    {
        obj->~T();
    }
};

#ifdef __GNUC__
template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton
{
#else
template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class singleton
{
#endif
    friend class CreatePolicy<T>;
    static T* pInstance_;
    static bool destroyed_;
    singleton(const singleton &rhs);
    singleton& operator=(const singleton&);

    static void onDeadReference()
    {
        throw std::runtime_error("dead reference!");
    }

    static void DestroySingleton()
    {
        CreatePolicy<T>::destroy(pInstance_);
        pInstance_ = 0;
        destroyed_ = true;
    }

protected:

#ifdef MAPNIK_THREADSAFE
        static std::mutex mutex_;
#endif
        singleton() {}
    public:
        static T& instance()
        {
            if (! pInstance_)
            {
#ifdef MAPNIK_THREADSAFE
                std::lock_guard<std::mutex> lock(mutex_);
#endif
                if (! pInstance_)
                {
                    if (destroyed_)
                    {
                        destroyed_ = false;
                        onDeadReference();
                    }
                    else
                    {
                        pInstance_ = CreatePolicy<T>::create();

                        // register destruction
                        std::atexit(&DestroySingleton);
                    }
                }
            }
            return *pInstance_;
        }
};

#ifdef MAPNIK_THREADSAFE
    template <typename T,
              template <typename U> class CreatePolicy> std::mutex singleton<T,CreatePolicy>::mutex_;
#endif

    template <typename T,
              template <typename U> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
    template <typename T,
              template <typename U> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

#ifdef _WINDOWS

// UTF8 <--> UTF16 conversion routines

MAPNIK_DECL std::string utf16_to_utf8(std::wstring const& wstr);
MAPNIK_DECL std::wstring utf8_to_utf16(std::string const& str);

#endif  // _WINDOWS

}

#endif // MAPNIK_UTILS_HPP
<commit_msg>implement DCLP using c++11  (http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTILS_HPP
#define MAPNIK_UTILS_HPP

#include <mapnik/config.hpp>

// stl
#include <stdexcept> // std::runtime_error
#include <cstdlib> // std::atexit
#include <new> // operator new
#include <atomic>
#ifdef MAPNIK_THREADSAFE
#include <mutex>
#endif

namespace mapnik
{

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }
    static void destroy(volatile T* obj)
    {
        obj->~T();
    }
};

#ifdef __GNUC__
template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton
{
#else
    template <typename T,
              template <typename U> class CreatePolicy=CreateStatic> class singleton
    {
#endif
        friend class CreatePolicy<T>;
        static std::atomic<T*> pInstance_;
        static bool destroyed_;
        singleton(const singleton &rhs);
        singleton& operator=(const singleton&);

        static void onDeadReference()
        {
            throw std::runtime_error("dead reference!");
        }

        static void DestroySingleton()
        {
            CreatePolicy<T>::destroy(pInstance_);
            pInstance_ = 0;
            destroyed_ = true;
        }

    protected:

#ifdef MAPNIK_THREADSAFE
        static std::mutex mutex_;
#endif
        singleton() {}

    public:
        static T& instance()
        {
            T * tmp = pInstance_.load(std::memory_order_acquire);
            if (tmp == nullptr)
            {
#ifdef MAPNIK_THREADSAFE
                std::lock_guard<std::mutex> lock(mutex_);
#endif
                tmp = pInstance_.load(std::memory_order_relaxed);
                if (tmp == nullptr)
                {
                    if (destroyed_)
                    {
                        destroyed_ = false;
                        onDeadReference();
                    }
                    else
                    {
                        tmp = CreatePolicy<T>::create();
                        pInstance_.store(tmp, std::memory_order_release);
                        // register destruction
                        std::atexit(&DestroySingleton);
                    }
                }
            }
            return *tmp;
        }
    };

#ifdef MAPNIK_THREADSAFE
    template <typename T,
              template <typename U> class CreatePolicy> std::mutex singleton<T,CreatePolicy>::mutex_;
#endif

    template <typename T,
              template <typename U> class CreatePolicy> std::atomic<T*> singleton<T,CreatePolicy>::pInstance_;
    template <typename T,
              template <typename U> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

#ifdef _WINDOWS

// UTF8 <--> UTF16 conversion routines

    MAPNIK_DECL std::string utf16_to_utf8(std::wstring const& wstr);
    MAPNIK_DECL std::wstring utf8_to_utf16(std::string const& str);

#endif  // _WINDOWS

}

#endif // MAPNIK_UTILS_HPP
<|endoftext|>


<commit_before>#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <string>
#include "lensfun.h"

class Image {
public:
    int width, height;
    int channel_size;
    lfPixelFormat pixel_format;
    std::vector<char> data;

    Image(int width, int height, lfPixelFormat pixel_format);
    Image() {};
    int get(int x, int y, int channel);
    void set(int x, int y, int channel, int value);
};

Image::Image(int width, int height, lfPixelFormat pixel_format) :
    width(width), height(height), pixel_format(pixel_format)
{
    switch (pixel_format) {
    case LF_PF_U8:
        channel_size = 1;
        break;
    case LF_PF_U16:
        channel_size = 2;
        break;
    default:
        throw std::string("Invalid pixel format");
    }
    data.resize(width * height * channel_size * 3);
}

int Image::get(int x, int y, int channel) {
    if (x < 0 || x >= width || y < 0 || y >= height)
        return 0;
    int position = channel_size * (3 * (y * width + x) + channel);
    return int(data[position]);
}

void Image::set(int x, int y, int channel, int value) {
    if (x >= 0 && x < width && y >= 0 && y < height) {
        int position = channel_size * (3 * (y * width + x) + channel);
        data[position] = char(value);
    }
}

std::istream& operator >>(std::istream &inputStream, Image &other)
{
    std::string magic_number;
    int maximum_color_value;
    inputStream >> magic_number;
    if (magic_number != "P6")
        throw std::string("Invalid input file.  Must start with 'P6'.");
    inputStream >> other.width >> other.height >> maximum_color_value;
    inputStream.get(); // skip the trailing white space
    switch (maximum_color_value) {
    case 255:
        other.pixel_format = LF_PF_U8;
        other.channel_size = 1;
        break;
    case 65535:
        other.pixel_format = LF_PF_U16;
        other.channel_size = 2;
        break;
    default:
        throw std::string("Invalid PPM file: Maximum color value must be 255 or 65535.");
    }
    size_t size = other.width * other.height * other.channel_size * 3;
    other.data.resize(size);
    inputStream.read(other.data.data(), size);
    return inputStream;
}

std::ostream& operator <<(std::ostream &outputStream, const Image &other)
{
    outputStream << "P6" << "\n"
                 << other.width << " "
                 << other.height << "\n"
                 << (other.pixel_format == LF_PF_U8 ? "255" : "65535") << "\n";
    outputStream.write(other.data.data(), other.data.size());
    return outputStream;
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "You must give path to input file.\n";
        return -1;
    }

    lfDatabase ldb;

    if (ldb.Load() != LF_NO_ERROR) {
        std::cerr << "Database could not be loaded\n";
        return -1;
    }

    const lfCamera *camera;
    const lfCamera **cameras = ldb.FindCamerasExt(NULL, "NEX-7");
    if (cameras && !cameras[1])
        camera = cameras[0];
    else {
        std::cerr << "Cannot find unique camera in database.  " << sizeof(cameras) << " cameras found.\n";
        lf_free(cameras);
        return -1;
    }
    lf_free(cameras);

    const lfLens *lens;
    const lfLens **lenses = ldb.FindLenses(camera, NULL, "E 50mm f/1.8 OSS");
    if (lenses && !lenses[1])
        lens = lenses[0];
    else if (!lenses[1]) {
        std::cerr << "Lens name ambiguous\n";
    } else {
        std::cerr << "Cannot find lens in database\n";
        lf_free(lenses);
        return -1;
    }
    lf_free(lenses);

    Image image;
    {
        std::ifstream file(argv[1], std::ios::binary);
        file >> image;
    }

    lfModifier modifier(camera->CropFactor, image.width, image.height, image.pixel_format);
    if (!modifier.EnableDistortionCorrection(lens, 50)) {
        std::cerr << "Failed to activate undistortion\n";
        return -1;
    }
    if (!modifier.EnableTCACorrection(lens, 50)) {
        std::cerr << "Failed to activate un-TCA\n";
        return -1;
    }
    std::vector<float> res(image.width * image.height * 2 * 3);
    modifier.ApplySubpixelGeometryDistortion(0, 0, image.width, image.height, res.data());

    Image new_image(image.width, image.height, image.pixel_format);
    for (int x = 0; x < image.width; x++)
        for (int y = 0; y < image.height; y++) {
            int position = 2 * 3 * (y * image.width + x);
            int source_x_R = int(res[position]);
            int source_y_R = int(res[position + 1]);
            int source_x_G = int(res[position + 2]);
            int source_y_G = int(res[position + 3]);
            int source_x_B = int(res[position + 4]);
            int source_y_B = int(res[position + 5]);
            new_image.set(x, y, 0, image.get(source_x_R, source_y_R, 0));
            new_image.set(x, y, 1, image.get(source_x_G, source_y_G, 1));
            new_image.set(x, y, 2, image.get(source_x_B, source_y_B, 2));
        }
    std::ofstream file("out.ppm", std::ios::binary);
    file << new_image;

    return 0;
}
<commit_msg>Added vignetting correction.<commit_after>#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <string>
#include "lensfun.h"

class Image {
public:
    int width, height;
    int channel_size;
    lfPixelFormat pixel_format;
    std::vector<char> data;

    Image(int width, int height, lfPixelFormat pixel_format);
    Image() {};
    int get(int x, int y, int channel);
    void set(int x, int y, int channel, int value);
};

Image::Image(int width, int height, lfPixelFormat pixel_format) :
    width(width), height(height), pixel_format(pixel_format)
{
    switch (pixel_format) {
    case LF_PF_U8:
        channel_size = 1;
        break;
    case LF_PF_U16:
        channel_size = 2;
        break;
    default:
        throw std::string("Invalid pixel format");
    }
    data.resize(width * height * channel_size * 3);
}

int Image::get(int x, int y, int channel) {
    if (x < 0 || x >= width || y < 0 || y >= height)
        return 0;
    int position = channel_size * (3 * (y * width + x) + channel);
    return int(data[position]);
}

void Image::set(int x, int y, int channel, int value) {
    if (x >= 0 && x < width && y >= 0 && y < height) {
        int position = channel_size * (3 * (y * width + x) + channel);
        data[position] = char(value);
    }
}

std::istream& operator >>(std::istream &inputStream, Image &other)
{
    std::string magic_number;
    int maximum_color_value;
    inputStream >> magic_number;
    if (magic_number != "P6")
        throw std::string("Invalid input file.  Must start with 'P6'.");
    inputStream >> other.width >> other.height >> maximum_color_value;
    inputStream.get(); // skip the trailing white space
    switch (maximum_color_value) {
    case 255:
        other.pixel_format = LF_PF_U8;
        other.channel_size = 1;
        break;
    case 65535:
        other.pixel_format = LF_PF_U16;
        other.channel_size = 2;
        break;
    default:
        throw std::string("Invalid PPM file: Maximum color value must be 255 or 65535.");
    }
    size_t size = other.width * other.height * other.channel_size * 3;
    other.data.resize(size);
    inputStream.read(other.data.data(), size);
    return inputStream;
}

std::ostream& operator <<(std::ostream &outputStream, const Image &other)
{
    outputStream << "P6" << "\n"
                 << other.width << " "
                 << other.height << "\n"
                 << (other.pixel_format == LF_PF_U8 ? "255" : "65535") << "\n";
    outputStream.write(other.data.data(), other.data.size());
    return outputStream;
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "You must give path to input file.\n";
        return -1;
    }

    lfDatabase ldb;

    if (ldb.Load() != LF_NO_ERROR) {
        std::cerr << "Database could not be loaded\n";
        return -1;
    }

    const lfCamera *camera;
    const lfCamera **cameras = ldb.FindCamerasExt(NULL, "NEX-7");
    if (cameras && !cameras[1])
        camera = cameras[0];
    else {
        std::cerr << "Cannot find unique camera in database.  " << sizeof(cameras) << " cameras found.\n";
        lf_free(cameras);
        return -1;
    }
    lf_free(cameras);

    const lfLens *lens;
    const lfLens **lenses = ldb.FindLenses(camera, NULL, "E 50mm f/1.8 OSS");
    if (lenses && !lenses[1])
        lens = lenses[0];
    else if (!lenses[1]) {
        std::cerr << "Lens name ambiguous\n";
    } else {
        std::cerr << "Cannot find lens in database\n";
        lf_free(lenses);
        return -1;
    }
    lf_free(lenses);

    Image image;
    {
        std::ifstream file(argv[1], std::ios::binary);
        file >> image;
    }

    lfModifier modifier(camera->CropFactor, image.width, image.height, image.pixel_format);
    if (!modifier.EnableDistortionCorrection(lens, 50)) {
        std::cerr << "Failed to activate undistortion\n";
        return -1;
    }
    if (!modifier.EnableTCACorrection(lens, 50)) {
        std::cerr << "Failed to activate un-TCA\n";
        return -1;
    }
    if (!modifier.EnableVignettingCorrection(lens, 50, 4.0, 1000)) {
        std::cerr << "Failed to activate devignetting\n";
        return -1;
    }

    modifier.ApplyColorModification(image.data.data(), 0, 0, image.width, image.height,
                                    LF_CR_3(RED, GREEN, BLUE), image.width * 3 * image.channel_size);

    std::vector<float> res(image.width * image.height * 2 * 3);
    modifier.ApplySubpixelGeometryDistortion(0, 0, image.width, image.height, res.data());

    Image new_image(image.width, image.height, image.pixel_format);
    for (int x = 0; x < image.width; x++)
        for (int y = 0; y < image.height; y++) {
            int position = 2 * 3 * (y * image.width + x);
            int source_x_R = int(res[position]);
            int source_y_R = int(res[position + 1]);
            int source_x_G = int(res[position + 2]);
            int source_y_G = int(res[position + 3]);
            int source_x_B = int(res[position + 4]);
            int source_y_B = int(res[position + 5]);
            new_image.set(x, y, 0, image.get(source_x_R, source_y_R, 0));
            new_image.set(x, y, 1, image.get(source_x_G, source_y_G, 1));
            new_image.set(x, y, 2, image.get(source_x_B, source_y_B, 2));
        }
    std::ofstream file("out.ppm", std::ios::binary);
    file << new_image;

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MetaImportComponent.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-05-03 13:30:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_METAIMPORTCOMPONENT_HXX
#define _XMLOFF_METAIMPORTCOMPONENT_HXX

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFO_HPP_
#include <com/sun/star/document/XDocumentInfo.hpp>
#endif

class XMLMetaImportComponent : public SvXMLImport
{
private:
    ::com::sun::star::uno::Reference<
        ::com::sun::star::document::XDocumentInfo>  xDocInfo;

public:
    // #110680#
    // XMLMetaImportComponent() throw();
    XMLMetaImportComponent(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory
        ) throw();

    ~XMLMetaImportComponent() throw();

protected:

    virtual SvXMLImportContext* CreateContext(
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    // XImporter
    virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
};

// global functions to support the component

::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
    XMLMetaImportComponent_getSupportedServiceNames()
    throw();

::rtl::OUString SAL_CALL XMLMetaImportComponent_getImplementationName()
    throw();

::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
    XMLMetaImportComponent_createInstance(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::lang::XMultiServiceFactory > & )
    throw( ::com::sun::star::uno::Exception );

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.330); FILE MERGED 2005/09/05 14:37:48 rt 1.4.330.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MetaImportComponent.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:37:54 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _XMLOFF_METAIMPORTCOMPONENT_HXX
#define _XMLOFF_METAIMPORTCOMPONENT_HXX

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFO_HPP_
#include <com/sun/star/document/XDocumentInfo.hpp>
#endif

class XMLMetaImportComponent : public SvXMLImport
{
private:
    ::com::sun::star::uno::Reference<
        ::com::sun::star::document::XDocumentInfo>  xDocInfo;

public:
    // #110680#
    // XMLMetaImportComponent() throw();
    XMLMetaImportComponent(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory
        ) throw();

    ~XMLMetaImportComponent() throw();

protected:

    virtual SvXMLImportContext* CreateContext(
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    // XImporter
    virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
};

// global functions to support the component

::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
    XMLMetaImportComponent_getSupportedServiceNames()
    throw();

::rtl::OUString SAL_CALL XMLMetaImportComponent_getImplementationName()
    throw();

::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
    XMLMetaImportComponent_createInstance(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::lang::XMultiServiceFactory > & )
    throw( ::com::sun::star::uno::Exception );

#endif

<|endoftext|>


<commit_before>
#include "bulkDataNTReaderListener.h"
#include "ACS_BD_Errors.h"
#include <iostream>
#include <iterator>

int BulkDataNTReaderListener::sleep_period=0;

BulkDataNTReaderListener::BulkDataNTReaderListener(const char* name, BulkDataCallback* cb)
: Logging::Loggable("BulkDataNT:"+string(name)),
				currentState_m(StartState),
				lost_packs(0),
				topicName_m(name),
				dataLength_m(0),
				frameCounter_m(0),
				totalFrames_m(0),
				logger_mp(0),
				loggerInitCount_m(0),
				callback_mp (cb)
{
	ACS_TRACE(__FUNCTION__);
	nestSample_m=0;
	frameDataReader_mp=0;
}//BulkDataNTReaderListener

BulkDataNTReaderListener::~BulkDataNTReaderListener ()
{
	ACS_TRACE(__FUNCTION__);
	if(logger_mp)
	{
		// we have to call doen as many times as we call init !!
		for(unsigned int i=0; i<loggerInitCount_m; i++)
			LoggingProxy::done();
		delete logger_mp; // ...  but we have just one proxy object for all DDS reader threads
	}
}//~BulkDataNTReaderListener

void BulkDataNTReaderListener::on_data_available(DDS::DataReader* reader)
{
	DDS::ReturnCode_t status;
	DDS::SampleInfo si ;
	ACSBulkData::BulkDataNTFrame message;
	unsigned char tmpArray[ACSBulkData::FRAME_MAX_LEN];

	if (frameDataReader_mp==NULL)
	{
		frameDataReader_mp = ACSBulkData::BulkDataNTFrameDataReader::narrow(reader);
		if  (  frameDataReader_mp==NULL) {
			cerr << "read: _narrow failed." << endl;
			exit(1);
		}//if
	}//if

	message.data.maximum(ACSBulkData::FRAME_MAX_LEN); //TBD constant from
	status = frameDataReader_mp->take_next_sample(message, si) ;

	if (status == DDS::RETCODE_OK)
	{
		if (si.valid_data == true)
		{
			switch(message.dataType)
			{
			case ACSBulkData::BD_PARAM:
			{
				cout << topicName_m << " startSend: parameter size: " << message.data.length() << endl;
				if (currentState_m==StartState || currentState_m==StopState)
				{
					dataLength_m = 0;
					frameCounter_m = 0;
					currentState_m = DataRcvState;
					message.data.to_array(tmpArray, message.data.length());
					callback_mp->cbStart(tmpArray, message.data.length());
				}
				else //error
				{
					ACS_BD_Errors::WrongFrameOrderCompletion wfo(__FILE__, __LINE__, __FUNCTION__);
					wfo.setDataType("BD_PARAM");
					wfo.setState(currentState_m);
					wfo.setFlow(topicName_m.c_str());
					wfo.setFrameCount(frameCounter_m);
					wfo.setTotalFrameCount(totalFrames_m);
					wfo.setFrameLength(message.data.length());
					getLogger(); //force initalization of logging sys TBD changed
					callback_mp->onError(wfo);
				}
				break;
			}//	case ACSBulkData::BD_PARAM:
			case ACSBulkData::BD_DATA:
			{
				if (currentState_m==DataRcvState)
				{
					if (dataLength_m==0) // we get first data frame
					{
						std::cout << " *************************   New sendData @ " << topicName_m << " *******************************" << std::endl;
						start_time = ACE_OS::gettimeofday();
						totalFrames_m = message.restDataLength+1;
						frameCounter_m = 0;
					}

					dataLength_m += message.data.length();
					frameCounter_m ++;

					if ( message.restDataLength>0)
					{
						if (nestSample_m!=0 && nestSample_m!=message.restDataLength)
						{
							cerr << "ERROR: " << topicName_m << "    " << ">>>> missed sample #: " << message.restDataLength << " for " << topicName_m << endl;
						}
						nestSample_m=message.restDataLength-1;
					}
					else //message.restDataLength==0 what means the last frame
					{
						ACE_Time_Value elapsed_time = ACE_OS::gettimeofday() - start_time;
						cout <<	topicName_m << " Received all data from sendData: " << dataLength_m << " Bytes in ";
						cout <<(elapsed_time.sec()+( elapsed_time.usec() / 1000000.0 ));
						cout << "secs. => Rate: ";
						cout << ((dataLength_m/(1024.0*1024.0))/(elapsed_time.sec()+( elapsed_time.usec() / 1000000.0 ))) << "MBytes/sec" << endl;

						DDS::SampleLostStatus s;
						reader->get_sample_lost_status(s);
						cerr << topicName_m << " LOST samples: \t\t total_count: " << s.total_count << " total_count_change: " << s.total_count_change << endl;
						dataLength_m = 0;
					}

					message.data.to_array(tmpArray, message.data.length());
					callback_mp->cbReceive(tmpArray, message.data.length());
				}
				else //error
				{
					ACS_BD_Errors::WrongFrameOrderCompletion wfo(__FILE__, __LINE__, __FUNCTION__);
					wfo.setDataType("BD_DATA");
					wfo.setState(currentState_m);
					wfo.setFlow(topicName_m.c_str());
					wfo.setFrameCount(frameCounter_m);
					wfo.setTotalFrameCount(totalFrames_m);
					wfo.setFrameLength(message.data.length());
					getLogger(); //force initalization of logging sys TBD changed
					callback_mp->onError(wfo);
				}
				break;
			}//case ACSBulkData::BD_DATA
			case ACSBulkData::BD_STOP:
			{
				if (currentState_m==DataRcvState)
				{
					currentState_m = StopState;
					cout << "===============================================================" << endl;
					if (dataLength_m==0)
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Got stop (BD_STOP) before any data (sendData)!"));
					}else
					{
						if (frameCounter_m != totalFrames_m)
						{
							std::cerr << "Not all data frames arrived: " << frameCounter_m << "/" << totalFrames_m << endl;
						}
					}
//					std::cout << "Arrived: " << frameCounter_m << "/" << totalFrames_m << endl;
					callback_mp->cbStop();
				}else
				{
					if (currentState_m==StopState)
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Stop (BD_STOP) arrived in stop state - will be ignored!"));
						//std::cerr << "WARNING: Stop (BD_STOP) arrived in stop state - ignored!" << std::endl;
					}
					else //StartState
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Stop (BD_STOP) arrived in start state: no parameter data (startSend) has arrived!"));
						//std::cerr << "WARNING: Stop (BD_STOP) arrived in start state: no data has been sent after start!" << std::endl;
					}//if-else
				}
				break;
			}//case ACSBulkData::BD_STOP
			default:
				ACS_BD_Errors::UnknownDataTypeCompletion udt(__FILE__, __LINE__, __FUNCTION__);
				udt.setDataType(message.dataType);
				udt.setFrameCount(frameCounter_m);
				udt.setTotalFrameCount(totalFrames_m);
				getLogger(); //force initalization of logging sys TBD
				callback_mp->onError(udt);
			}//switch
		}else if (si.instance_state == DDS::NOT_ALIVE_DISPOSED_INSTANCE_STATE)
		{
			cout << "instance is disposed" << endl;
		}
		else if (si.instance_state == DDS::NOT_ALIVE_NO_WRITERS_INSTANCE_STATE)
		{
			cout << "instance is unregistered" << endl;
		}
		else
		{
			cout << "BulkDataNTReaderListener(" << topicName_m << ")::on_data_available:";
			cout << " received unknown instance state " << si.instance_state;
			cout << endl;
		}
	}else if (status == DDS::RETCODE_NO_DATA) {
		cerr << "ERROR: on_data_available DDS::RETCODE_NO_DATA!" << endl;
	}
	else
	{
		cerr << "ERROR: on_data_available status: " << status << endl;
	}//if(status)
}//on_data_available

void BulkDataNTReaderListener::on_requested_deadline_missed (
		DDS::DataReader*,
		const DDS::RequestedDeadlineMissedStatus& )
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << ")::on_requested_deadline_missed" << endl;
}

void BulkDataNTReaderListener::on_requested_incompatible_qos (
		DDS::DataReader*,
	const DDS::RequestedIncompatibleQosStatus&)
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << ")::on_requested_incompatible_qos" << endl;
}

void BulkDataNTReaderListener::on_liveliness_changed (
		DDS::DataReader*, const DDS::LivelinessChangedStatus& lcs)
{
	if (lcs.alive_count_change>0)
	{
		for(int i=0; i<lcs.alive_count_change; i++)
		{
			ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
					(LM_INFO, "A new sender has connected to flow: %s of the stream: %s. Total alive connection(s): %d",
							callback_mp->getFlowName(), callback_mp->getStreamName(),
							lcs.alive_count));
			callback_mp->onSenderConnect();
		}//for
	}else
	{
		for(int i=lcs.alive_count_change; i<0; i++)
		{
			ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
					(LM_INFO, "A sender has disconnected to flow: %s of the stream: %s. Total alive connection(s): %d",
							callback_mp->getFlowName(), callback_mp->getStreamName(),
							lcs.alive_count));
			callback_mp->onSenderDisconnect();
		}//for
	}//if-else
}//on_liveliness_changed

void BulkDataNTReaderListener::on_subscription_matched (
		DDS::DataReader*, const DDS::SubscriptionMatchedStatus& )
{
	ACS_TRACE(__FUNCTION__);
}//on_subscription_matched

void BulkDataNTReaderListener::on_sample_rejected(
		DDS::DataReader*, const DDS::SampleRejectedStatus& srs)
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << "::on_sample_rejected SampleRejectedStatus.last_reason: ";
	cerr << srs.last_reason << " SampleRejectedStatus.total_count_change: " << srs.total_count_change;
	cerr << " SampleRejectedStatus.total_count: " << srs.total_count << endl;
}//on_sample_rejected

void BulkDataNTReaderListener::on_sample_lost(
		DDS::DataReader*, const DDS::SampleLostStatus& s)
{
	cerr << endl << endl << "BulkDataNTReaderListener(" << topicName_m << "::on_sample_lost: ";
	cerr << "total_count: " << s.total_count << " total_count_change: " << s.total_count_change << endl << endl;
}//on_sample_lost

Logging::Logger::LoggerSmartPtr BulkDataNTReaderListener::getLogger ()
{
	// this code is a bit dirty, but wee need to initialize loggerproxy per thread
	//isThreadInit return 0 if it is initialized !!!
	if (LoggingProxy::isInitThread() )
	{
		//TBD here we have to set centralized loggger as well, but we need some support from logging
		if (logger_mp==0) //if we do not have a logger we create one for all DDS threads
			logger_mp = new LoggingProxy(0, 0, 31);
		LoggingProxy::init(logger_mp);
		loggerInitCount_m++; // we initialized Proxy another time
	}
	return Logging::Loggable::getLogger();
}//getLogger
<commit_msg>handling narrow error<commit_after>
#include "bulkDataNTReaderListener.h"
#include "ACS_BD_Errors.h"
#include <ACS_DDS_Errors.h>
#include <iostream>
#include <iterator>

int BulkDataNTReaderListener::sleep_period=0;

BulkDataNTReaderListener::BulkDataNTReaderListener(const char* name, BulkDataCallback* cb)
: Logging::Loggable("BulkDataNT:"+string(name)),
				currentState_m(StartState),
				lost_packs(0),
				topicName_m(name),
				dataLength_m(0),
				frameCounter_m(0),
				totalFrames_m(0),
				logger_mp(0),
				loggerInitCount_m(0),
				callback_mp (cb)
{
	ACS_TRACE(__FUNCTION__);
	nextFrame_m=0;
	frameDataReader_mp=0;
}//BulkDataNTReaderListener

BulkDataNTReaderListener::~BulkDataNTReaderListener ()
{
	ACS_TRACE(__FUNCTION__);
	if(logger_mp)
	{
		// we have to call doen as many times as we call init !!
		for(unsigned int i=0; i<loggerInitCount_m; i++)
			LoggingProxy::done();
		delete logger_mp; // ...  but we have just one proxy object for all DDS reader threads
	}
}//~BulkDataNTReaderListener

void BulkDataNTReaderListener::on_data_available(DDS::DataReader* reader)
{
	DDS::ReturnCode_t status;
	DDS::SampleInfo si ;
	ACSBulkData::BulkDataNTFrame message;
	unsigned char tmpArray[ACSBulkData::FRAME_MAX_LEN];

	if (frameDataReader_mp==NULL)
	{
		frameDataReader_mp = ACSBulkData::BulkDataNTFrameDataReader::narrow(reader);
		if  (  frameDataReader_mp==NULL) {
			ACS_DDS_Errors::DDSNarrowFailedCompletion nerr(__FILE__, __LINE__, __FUNCTION__);
			nerr.setVariable("frameDataReader_mp");
			nerr.setNarrowType("ACSBulkData::BulkDataNTFrameDataReader");
			getLogger(); //force initialization of logging sys TBD changed
			callback_mp->onError(nerr);
		}//if
	}//if

	message.data.maximum(ACSBulkData::FRAME_MAX_LEN); //TBD constant from
	status = frameDataReader_mp->take_next_sample(message, si) ;

	if (status == DDS::RETCODE_OK)
	{
		if (si.valid_data == true)
		{
			switch(message.dataType)
			{
			case ACSBulkData::BD_PARAM:
			{
				cout << topicName_m << " startSend: parameter size: " << message.data.length() << endl;
				if (currentState_m==StartState || currentState_m==StopState)
				{
					dataLength_m = 0;
					frameCounter_m = 0;
					currentState_m = DataRcvState;
					message.data.to_array(tmpArray, message.data.length());
					callback_mp->cbStart(tmpArray, message.data.length());
				}
				else //error
				{
					ACS_BD_Errors::WrongFrameOrderCompletion wfo(__FILE__, __LINE__, __FUNCTION__);
					wfo.setDataType("BD_PARAM"); wfo.setState(currentState_m);
					wfo.setFlow(topicName_m.c_str()); wfo.setFrameCount(frameCounter_m);
					wfo.setTotalFrameCount(totalFrames_m); wfo.setFrameLength(message.data.length());
					getLogger(); //force initialization of logging sys TBD changed
					callback_mp->onError(wfo);
				}
				break;
			}//	case ACSBulkData::BD_PARAM:
			case ACSBulkData::BD_DATA:
			{
				if (currentState_m==DataRcvState)
				{
					if (dataLength_m==0) // we get the first data frame
					{
						std::cout << " *************************   New sendData @ " << topicName_m << " *******************************" << std::endl;
						start_time = ACE_OS::gettimeofday();
						totalFrames_m = message.restDataLength+1;
						frameCounter_m = 0;
					}

					dataLength_m += message.data.length();
					frameCounter_m ++;

					if ( message.restDataLength>0)
					{
						if (nextFrame_m!=0 && nextFrame_m!=message.restDataLength)
						{
							cerr << "ERROR: " << topicName_m << "    " << ">>>> missed frame  #: " << message.restDataLength << " for " << topicName_m << endl;
						}
						nextFrame_m = message.restDataLength-1;
					}
					else //message.restDataLength==0 what means the last frame
					{
						ACE_Time_Value elapsed_time = ACE_OS::gettimeofday() - start_time;
						cout <<	topicName_m << " Received all data from sendData: " << dataLength_m << " Bytes in ";
						cout <<(elapsed_time.sec()+( elapsed_time.usec() / 1000000.0 ));
						cout << "secs. => Rate: ";
						cout << ((dataLength_m/(1024.0*1024.0))/(elapsed_time.sec()+( elapsed_time.usec() / 1000000.0 ))) << "MBytes/sec" << endl;

						DDS::SampleLostStatus s;
						reader->get_sample_lost_status(s);
						cerr << topicName_m << " LOST samples: \t\t total_count: " << s.total_count << " total_count_change: " << s.total_count_change << endl;
						dataLength_m = 0;
					}

					message.data.to_array(tmpArray, message.data.length());
					callback_mp->cbReceive(tmpArray, message.data.length());
				}
				else //error
				{
					ACS_BD_Errors::WrongFrameOrderCompletion wfo(__FILE__, __LINE__, __FUNCTION__);
					wfo.setDataType("BD_DATA"); wfo.setState(currentState_m);
					wfo.setFlow(topicName_m.c_str()); wfo.setFrameCount(frameCounter_m);
					wfo.setTotalFrameCount(totalFrames_m); wfo.setFrameLength(message.data.length());
					getLogger(); //force initalization of logging sys TBD changed
					callback_mp->onError(wfo);
				}
				break;
			}//case ACSBulkData::BD_DATA
			case ACSBulkData::BD_STOP:
			{
				if (currentState_m==DataRcvState)
				{
					currentState_m = StopState;
					cout << "===============================================================" << endl;
					if (dataLength_m==0)
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Got stop (BD_STOP) before any data (sendData)!"));
					}else
					{
						if (frameCounter_m != totalFrames_m)
						{
							std::cerr << "Not all data frames arrived: " << frameCounter_m << "/" << totalFrames_m << endl;
						}
					}
//					std::cout << "Arrived: " << frameCounter_m << "/" << totalFrames_m << endl;
					callback_mp->cbStop();
				}else
				{
					if (currentState_m==StopState)
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Stop (BD_STOP) arrived in stop state - will be ignored!"));
						//std::cerr << "WARNING: Stop (BD_STOP) arrived in stop state - ignored!" << std::endl;
					}
					else //StartState
					{
						ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
								(LM_WARNING, "Stop (BD_STOP) arrived in start state: no parameter data (startSend) has arrived!"));
						//std::cerr << "WARNING: Stop (BD_STOP) arrived in start state: no data has been sent after start!" << std::endl;
					}//if-else
				}
				break;
			}//case ACSBulkData::BD_STOP
			default:
				ACS_BD_Errors::UnknownDataTypeCompletion udt(__FILE__, __LINE__, __FUNCTION__);
				udt.setDataType(message.dataType);
				udt.setFrameCount(frameCounter_m);
				udt.setTotalFrameCount(totalFrames_m);
				getLogger(); //force initalization of logging sys TBD
				callback_mp->onError(udt);
			}//switch
		}else if (si.instance_state == DDS::NOT_ALIVE_DISPOSED_INSTANCE_STATE)
		{
			cout << "instance is disposed" << endl;
		}
		else if (si.instance_state == DDS::NOT_ALIVE_NO_WRITERS_INSTANCE_STATE)
		{
			cout << "instance is unregistered" << endl;
		}
		else
		{
			cout << "BulkDataNTReaderListener(" << topicName_m << ")::on_data_available:";
			cout << " received unknown instance state " << si.instance_state;
			cout << endl;
		}
	}else if (status == DDS::RETCODE_NO_DATA) {
		cerr << "ERROR: on_data_available DDS::RETCODE_NO_DATA!" << endl;
	}
	else
	{
		cerr << "ERROR: on_data_available status: " << status << endl;
	}//if(status)
}//on_data_available

void BulkDataNTReaderListener::on_requested_deadline_missed (
		DDS::DataReader*,
		const DDS::RequestedDeadlineMissedStatus& )
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << ")::on_requested_deadline_missed" << endl;
}

void BulkDataNTReaderListener::on_requested_incompatible_qos (
		DDS::DataReader*,
	const DDS::RequestedIncompatibleQosStatus&)
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << ")::on_requested_incompatible_qos" << endl;
}

void BulkDataNTReaderListener::on_liveliness_changed (
		DDS::DataReader*, const DDS::LivelinessChangedStatus& lcs)
{
	if (lcs.alive_count_change>0)
	{
		for(int i=0; i<lcs.alive_count_change; i++)
		{
			ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
					(LM_INFO, "A new sender has connected to flow: %s of the stream: %s. Total alive connection(s): %d",
							callback_mp->getFlowName(), callback_mp->getStreamName(),
							lcs.alive_count));
			callback_mp->onSenderConnect();
		}//for
	}else
	{
		for(int i=lcs.alive_count_change; i<0; i++)
		{
			ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__,
					(LM_INFO, "A sender has disconnected to flow: %s of the stream: %s. Total alive connection(s): %d",
							callback_mp->getFlowName(), callback_mp->getStreamName(),
							lcs.alive_count));
			callback_mp->onSenderDisconnect();
		}//for
	}//if-else
}//on_liveliness_changed

void BulkDataNTReaderListener::on_subscription_matched (
		DDS::DataReader*, const DDS::SubscriptionMatchedStatus& )
{
	ACS_TRACE(__FUNCTION__);
}//on_subscription_matched

void BulkDataNTReaderListener::on_sample_rejected(
		DDS::DataReader*, const DDS::SampleRejectedStatus& srs)
{
	cerr << "BulkDataNTReaderListener(" << topicName_m << "::on_sample_rejected SampleRejectedStatus.last_reason: ";
	cerr << srs.last_reason << " SampleRejectedStatus.total_count_change: " << srs.total_count_change;
	cerr << " SampleRejectedStatus.total_count: " << srs.total_count << endl;
}//on_sample_rejected

void BulkDataNTReaderListener::on_sample_lost(
		DDS::DataReader*, const DDS::SampleLostStatus& s)
{
	cerr << endl << endl << "BulkDataNTReaderListener(" << topicName_m << "::on_sample_lost: ";
	cerr << "total_count: " << s.total_count << " total_count_change: " << s.total_count_change << endl << endl;
}//on_sample_lost

Logging::Logger::LoggerSmartPtr BulkDataNTReaderListener::getLogger ()
{
	// this code is a bit dirty, but wee need to initialize loggerproxy per thread
	//isThreadInit return 0 if it is initialized !!!
	if (LoggingProxy::isInitThread() )
	{
		//TBD here we have to set centralized loggger as well, but we need some support from logging
		if (logger_mp==0) //if we do not have a logger we create one for all DDS threads
			logger_mp = new LoggingProxy(0, 0, 31);
		LoggingProxy::init(logger_mp);
		loggerInitCount_m++; // we initialized Proxy another time
	}
	return Logging::Loggable::getLogger();
}//getLogger
<|endoftext|>


<commit_before>/* Copyright (C) 2018 INRA
 *
 * 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.
 */

#ifndef ORG_VLEPROJECT_BARYONYX_SOLVER_SPARSE_MATRIX_HPP
#define ORG_VLEPROJECT_BARYONYX_SOLVER_SPARSE_MATRIX_HPP

#include <baryonyx/core>

#include <algorithm>
#include <memory>

#include "fixed_array.hpp"
#include "itm.hpp"

namespace baryonyx {

template<typename Index>
class sparse_matrix
{
public:
    using size_type = std::size_t;
    using index_type = Index;

    struct col_value
    {
        col_value() = default;

        col_value(int value_, int row_)
          : value(value_)
          , row(row_)
        {}

        int value = -1;
        int row = -1;
    };

    struct row_value
    {
        row_value() = default;

        row_value(int value_, int column_)
          : value(value_)
          , column(column_)
        {}

        int value = -1;
        int column = -1;
    };

protected:
    using vector_access = fixed_array<int>;
    using row_vector_access = fixed_array<row_value>;
    using col_vector_access = fixed_array<col_value>;

    vector_access m_rows_access;
    vector_access m_cols_access;
    row_vector_access m_rows_values;
    col_vector_access m_cols_values;

public:
    using row_iterator = typename row_vector_access::iterator;
    using col_iterator = typename col_vector_access::iterator;
    using const_row_iterator = typename row_vector_access::const_iterator;
    using const_col_iterator = typename col_vector_access::const_iterator;

    explicit sparse_matrix(const std::vector<itm::merged_constraint>& csts,
                           int rows,
                           int cols)
      : m_rows_access(rows)
      , m_cols_access(cols)
    {
        int elem = 0;

        for (int i = 0, e = rows; i != e; ++i)
            elem += static_cast<int>(csts[i].elements.size());

        row_vector_access(elem).swap(m_rows_values);
        col_vector_access(elem).swap(m_cols_values);

        //
        // First, we build a vector of access to all elements in the matrix
        // different to 0. Then, we sort accessors according to the column id
        // then we assign a unique identifier for each accessors and then we
        // sort accessors according to the row id. This code enable the
        // construction of the r_rows_values with pointers to the
        // r_cols_values.
        //

        struct access
        {
            access() = default;

            access(int row_, int col_, function_element fct_)
              : row(row_)
              , col(col_)
              , fct(fct_)
            {}

            int row;
            int col;
            int id;
            function_element fct;
        };

        // using access = std::tuple<int, int, int, function_element>;

        std::vector<access> accessors(elem);
        accessors.clear();
        for (int i = 0; i != rows; ++i)
            for (const auto& fct_elem : csts[i].elements)
                accessors.emplace_back(i, fct_elem.variable_index, fct_elem);

        std::stable_sort(
          accessors.begin(),
          accessors.end(),
          [](const auto& lhs, const auto& rhs) { return lhs.row < rhs.row; });

        fixed_array<int> rinit(rows, 0);
        int row = accessors[0].row;
        int nb_row = 0;
        for (int i = 0; i != elem; ++i) {
            if (row != accessors[i].row) {
                rinit[row] = nb_row;
                nb_row = 0;
                row = accessors[i].row;
            }
            ++nb_row;

            accessors[i].id = i;
            m_rows_values[i] = { i, accessors[i].col };
        }

        std::stable_sort(
          accessors.begin(),
          accessors.end(),
          [](const auto& lhs, const auto& rhs) { return lhs.col < rhs.col; });

        fixed_array<int> cinit(cols, 0);
        int col = accessors[0].col;
        int nb_col = 0;

        for (int i = 0; i != elem; ++i) {
            if (col != accessors[i].col) {
                cinit[col] = nb_col;
                nb_col = 0;
                col = accessors[i].col;
            }
            ++nb_col;

            m_cols_values[i] = { m_rows_values[accessors[i].id].value,
                                 accessors[i].row };
        }

        for (int i = 0, current = 0; i != rows; ++i) {
            m_rows_access[i] = current;
            current += rinit[i];
        }

        for (int i = 0, current = 0; i != cols; ++i) {
            m_cols_access[i] = current;
            current += cinit[i];
        }
    }

    std::tuple<row_iterator, row_iterator> row(int row) noexcept
    {
        m_check_index(row, 0);

        row_iterator begin = m_rows_values.begin() + m_rows_access[row];
        row_iterator end = m_rows_values.end();

        if (static_cast<std::size_t>(row + 1) < m_rows_access.size())
            end = begin + (m_rows_access[row + 1] - m_rows_access[row]);

        return std::make_tuple(begin, end);
    }

    std::tuple<col_iterator, col_iterator> column(int col) noexcept
    {
        m_check_index(0, col);

        col_iterator begin = m_cols_values.begin() + m_cols_access[col];
        col_iterator end = m_cols_values.end();

        if (static_cast<std::size_t>(col + 1) < m_cols_access.size())
            end = begin + (m_cols_access[col + 1] - m_cols_access[col]);

        return std::make_tuple(begin, end);
    }

    std::tuple<const_row_iterator, const_row_iterator> row(int row) const
      noexcept
    {
        m_check_index(row, 0);

        const_row_iterator begin = m_rows_values.begin() + m_rows_access[row];
        const_row_iterator end = m_rows_values.end();

        if (static_cast<std::size_t>(row + 1) < m_rows_access.size())
            end = begin + (m_rows_access[row + 1] - m_rows_access[row]);

        return std::make_tuple(begin, end);
    }

    std::tuple<const_col_iterator, const_col_iterator> column(int col) const
      noexcept
    {
        m_check_index(0, col);

        const_col_iterator begin = m_cols_values.begin() + m_cols_access[col];
        const_col_iterator end = m_cols_values.end();

        if (static_cast<std::size_t>(col + 1) < m_cols_access.size())
            end = begin + (m_cols_access[col + 1] - m_cols_access[col]);

        return std::make_tuple(begin, end);
    }

private:
    void m_check_index(index_type row, index_type col) const noexcept
    {
#ifdef NDEBUG
        (void)row;
        (void)col;
#else
        assert(col >= 0 && col < length(m_cols_access) &&
               "SparseArray: bad column access");

        assert(row >= 0 && row < length(m_rows_access) &&
               "SparseArray: bad row access");
#endif
    }
};
}

#endif
<commit_msg>matrix: added statistics about size and memory<commit_after>/* Copyright (C) 2018 INRA
 *
 * 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.
 */

#ifndef ORG_VLEPROJECT_BARYONYX_SOLVER_SPARSE_MATRIX_HPP
#define ORG_VLEPROJECT_BARYONYX_SOLVER_SPARSE_MATRIX_HPP

#include <baryonyx/core>

#include <algorithm>
#include <memory>
#include <string>

#include "fixed_array.hpp"
#include "itm.hpp"

namespace baryonyx {

template<typename Index>
class sparse_matrix
{
public:
    using size_type = std::size_t;
    using index_type = Index;

    struct col_value
    {
        col_value() = default;

        col_value(int value_, int row_)
          : value(value_)
          , row(row_)
        {}

        int value = -1;
        int row = -1;
    };

    struct row_value
    {
        row_value() = default;

        row_value(int value_, int column_)
          : value(value_)
          , column(column_)
        {}

        int value = -1;
        int column = -1;
    };

protected:
    using vector_access = fixed_array<int>;
    using row_vector_access = fixed_array<row_value>;
    using col_vector_access = fixed_array<col_value>;

    vector_access m_rows_access;
    vector_access m_cols_access;
    row_vector_access m_rows_values;
    col_vector_access m_cols_values;

public:
    using row_iterator = typename row_vector_access::iterator;
    using col_iterator = typename col_vector_access::iterator;
    using const_row_iterator = typename row_vector_access::const_iterator;
    using const_col_iterator = typename col_vector_access::const_iterator;

    explicit sparse_matrix(const std::vector<itm::merged_constraint>& csts,
                           int rows,
                           int cols)
      : m_rows_access(rows)
      , m_cols_access(cols)
    {
        int elem = 0;

        for (int i = 0, e = rows; i != e; ++i)
            elem += static_cast<int>(csts[i].elements.size());

        row_vector_access(elem).swap(m_rows_values);
        col_vector_access(elem).swap(m_cols_values);

        {
            std::size_t ets = m_rows_access.size() * sizeof(int) +
                              m_cols_access.size() * sizeof(int) +
                              m_rows_values.size() * sizeof(row_value) +
                              m_cols_values.size() * sizeof(col_value);

            double estimated;
            std::string type;

            if (ets > (1024 * 1024 * 1024)) {
                estimated = ets / (1024 * 1024 * 1024);
                type = "GB";
            } else if (ets > 1024 * 1024) {
                estimated = ets / (1024 * 1024);
                type = "MB";
            }
            if (ets > 1024) {
                estimated = ets / 1024;
                type = "KB";
            } else {
                estimated = ets;
                type = "B";
            }

            fmt::print("  - sparse_matrix [rows:{} columns:{} elements:{} "
                       "memory: {}{}]\n",
                       rows,
                       cols,
                       elem,
                       estimated,
                       type);
        }

        //
        // First, we build a vector of access to all elements in the matrix
        // different to 0. Then, we sort accessors according to the column id
        // then we assign a unique identifier for each accessors and then we
        // sort accessors according to the row id. This code enable the
        // construction of the r_rows_values with pointers to the
        // r_cols_values.
        //

        struct access
        {
            access() = default;

            access(int row_, int col_, function_element fct_)
              : row(row_)
              , col(col_)
              , fct(fct_)
            {}

            int row;
            int col;
            int id;
            function_element fct;
        };

        // using access = std::tuple<int, int, int, function_element>;

        std::vector<access> accessors(elem);
        accessors.clear();
        for (int i = 0; i != rows; ++i)
            for (const auto& fct_elem : csts[i].elements)
                accessors.emplace_back(i, fct_elem.variable_index, fct_elem);

        std::stable_sort(
          accessors.begin(),
          accessors.end(),
          [](const auto& lhs, const auto& rhs) { return lhs.row < rhs.row; });

        fixed_array<int> rinit(rows, 0);
        int row = accessors[0].row;
        int nb_row = 0;
        for (int i = 0; i != elem; ++i) {
            if (row != accessors[i].row) {
                rinit[row] = nb_row;
                nb_row = 0;
                row = accessors[i].row;
            }
            ++nb_row;

            accessors[i].id = i;
            m_rows_values[i] = { i, accessors[i].col };
        }

        std::stable_sort(
          accessors.begin(),
          accessors.end(),
          [](const auto& lhs, const auto& rhs) { return lhs.col < rhs.col; });

        fixed_array<int> cinit(cols, 0);
        int col = accessors[0].col;
        int nb_col = 0;

        for (int i = 0; i != elem; ++i) {
            if (col != accessors[i].col) {
                cinit[col] = nb_col;
                nb_col = 0;
                col = accessors[i].col;
            }
            ++nb_col;

            m_cols_values[i] = { m_rows_values[accessors[i].id].value,
                                 accessors[i].row };
        }

        for (int i = 0, current = 0; i != rows; ++i) {
            m_rows_access[i] = current;
            current += rinit[i];
        }

        for (int i = 0, current = 0; i != cols; ++i) {
            m_cols_access[i] = current;
            current += cinit[i];
        }
    }

    std::tuple<row_iterator, row_iterator> row(int row) noexcept
    {
        m_check_index(row, 0);

        row_iterator begin = m_rows_values.begin() + m_rows_access[row];
        row_iterator end = m_rows_values.end();

        if (static_cast<std::size_t>(row + 1) < m_rows_access.size())
            end = begin + (m_rows_access[row + 1] - m_rows_access[row]);

        return std::make_tuple(begin, end);
    }

    std::tuple<col_iterator, col_iterator> column(int col) noexcept
    {
        m_check_index(0, col);

        col_iterator begin = m_cols_values.begin() + m_cols_access[col];
        col_iterator end = m_cols_values.end();

        if (static_cast<std::size_t>(col + 1) < m_cols_access.size())
            end = begin + (m_cols_access[col + 1] - m_cols_access[col]);

        return std::make_tuple(begin, end);
    }

    std::tuple<const_row_iterator, const_row_iterator> row(int row) const
      noexcept
    {
        m_check_index(row, 0);

        const_row_iterator begin = m_rows_values.begin() + m_rows_access[row];
        const_row_iterator end = m_rows_values.end();

        if (static_cast<std::size_t>(row + 1) < m_rows_access.size())
            end = begin + (m_rows_access[row + 1] - m_rows_access[row]);

        return std::make_tuple(begin, end);
    }

    std::tuple<const_col_iterator, const_col_iterator> column(int col) const
      noexcept
    {
        m_check_index(0, col);

        const_col_iterator begin = m_cols_values.begin() + m_cols_access[col];
        const_col_iterator end = m_cols_values.end();

        if (static_cast<std::size_t>(col + 1) < m_cols_access.size())
            end = begin + (m_cols_access[col + 1] - m_cols_access[col]);

        return std::make_tuple(begin, end);
    }

private:
    void m_check_index(index_type row, index_type col) const noexcept
    {
#ifdef NDEBUG
        (void)row;
        (void)col;
#else
        assert(col >= 0 && col < length(m_cols_access) &&
               "SparseArray: bad column access");

        assert(row >= 0 && row < length(m_rows_access) &&
               "SparseArray: bad row access");
#endif
    }
};
}

#endif
<|endoftext|>


<commit_before>// This file is part of Playslave-C++.
// Playslave-C++ is licenced under the MIT license: see LICENSE.txt.

/**
 * @file
 * Declaration of the AudioOutput class.
 * @see audio/audio_output.cpp
 */

#ifndef PS_AUDIO_OUTPUT_HPP
#define PS_AUDIO_OUTPUT_HPP

#include <chrono>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "portaudio.h"
#include "portaudiocpp/CallbackInterface.hxx"
namespace portaudio {
class Stream;
}

template <typename RepT, typename SampleCountT>
class RingBuffer;

#include "audio_decoder.hpp"
#include "audio_resample.hpp"

/// Type of results emitted during the play callback step.
using PlayCallbackStepResult = std::pair<PaStreamCallbackResult, unsigned long>;

/**
 * Abstract class for objects that can configure PortAudio streams for audio
 * files.
 */
class StreamConfigurator {
public:
	/**
	 * Configures and returns a PortAudio stream for the given decoder.
	 * @param cb The object that PortAudio will call to receive audio.
	 * @param decoder The decoder whose output will be fed into the stream.
	 * @return The configured PortAudio stream.
	 */
	virtual portaudio::Stream *Configure(
	                portaudio::CallbackInterface &cb,
	                const AudioDecoder &decoder) const = 0;
};

/**
 * An audio file and its associated decoder, ringbuffer and output stream.
 *
 * AudioOutput contains all state pertaining to the output of one file to one
 * stream.  It contains an AudioDecoder, a RingBuffer, and implements the
 * portaudio::CallbackInterface (allowing it to send PortAudio decoded audio)
 * and SampleByteConverter (allowing it to be queried for conversions from
 * sample counts to byte counts).
 */
class AudioOutput : portaudio::CallbackInterface, SampleByteConverter {
public:
	/**
	 * Loads a file and constructs an AudioOutput for it.
	 * @param path The absolute path to the file to open.
	 * @param c An object that can configure PortAudio streams.  This will
	 *   usually be the AudioSystem.
	 * @see AudioSystem::Load
	 */
	AudioOutput(const std::string &path, const StreamConfigurator &c);
	~AudioOutput();

	/**
	 * Starts the audio stream.
	 * @see Stop
	 * @see IsHalted
	 */
	void Start();

	/**
	 * Stops the audio stream.
	 * @see Start
	 * @see IsHalted
	 */
	void Stop();

	/**
	 * Performs an update cycle on this AudioOutput.
	 * This ensures the ring buffer has output to offer to the sound driver.
	 * It does this by by asking the AudioDecoder to decode if necessary.
	 * @return True if there is more output to send to the sound card; false
	 *   otherwise.
	 */
	bool Update();

	/**
	 * Checks to see if audio playback has stopped.
	 * @return True if the audio stream is inactive; false otherwise.
	 * @see Start
	 * @see Stop
	 */
	bool IsStopped();

	/**
	 * Returns whether the current frame has been finished.
	 * If this is true, then either the frame is empty, or all of the
	 * samples in the frame have been fed to the ringbuffer.
	 * @return  True if the frame is finished; false otherwise.
	 */
	bool FrameFinished();

	/**
	 * Returns whether the audio file has ended.
	 * This does NOT mean that playback has ended; the ring buffer may still
	 * have samples waiting to send to the audio library.
	 * @return  True if there is no audio left to decode; false otherwise.
	 */
	bool FileEnded();

	/**
	 * Return the current position, as a std::chrono::duration.
	 * @return The current position in the audio.
	 */
	template <typename R>
	R CurrentPosition()
	{
		return std::chrono::duration_cast<R>(
		                CurrentPositionMicroseconds());
	}

	/**
	 * Gets the current played position in the song, in microseconds.
	 * As this may be executing whilst the playing callback is running,
	 * do not expect it to be highly accurate.
	 * @return The current position, in microseconds.
	 */
	std::chrono::microseconds CurrentPositionMicroseconds();

	/**
	 * Seek to a position expressed as a std::chrono::duration.
	 * @param position The position to seek to in the audio.
	 */
	template <typename R>
	void SeekToPosition(R position)
	{
		SeekToPositionMicroseconds(std::chrono::duration_cast<
		                std::chrono::microseconds>(position));
	}

	/**
	 * Attempts to seek to the given position in microseconds.
	 * @param microseconds The position to seek to, in microseconds.
	 */
	void SeekToPositionMicroseconds(std::chrono::microseconds microseconds);

private:
	// Type for the ring buffer.
	using RingBuf = RingBuffer<char, std::uint64_t>;

	/// n, where 2^n is the capacity of the AudioOutput ring buffer.
	/// @see RINGBUF_SIZE
	static const size_t RINGBUF_POWER;

	/// The number of bytes to pre-load into the buffer before playing.
	static const size_t SPINUP_SIZE;

	bool file_ended; ///< Whether the current file has stopped decoding.

	/// The audio decoder providing the actual audio data.
	std::unique_ptr<AudioDecoder> av;

	/// The current decoded frame.
	std::vector<char> frame;

	/// The current position in the current decoded frame.
	std::vector<char>::iterator frame_iterator;

	/// The ring buffer used to transfer samples to the playing callback.
	std::unique_ptr<RingBuf> ring_buf;

	/// The PortAudio stream to which this AudioOutput outputs.
	std::unique_ptr<portaudio::Stream> out_strm;

	/// The current position, in samples.
	uint64_t position_sample_count;

	/**
	 * Clears the current frame and its iterator.
	 */
	void ClearFrame();

	std::uint64_t ByteCountForSampleCount(
	                std::uint64_t sample_count) const override;
	std::uint64_t SampleCountForByteCount(
	                std::uint64_t sample_count) const override;

	/**
	 * The callback proper.
	 * This is executed in a separate thread by PortAudio once a stream is
	 * playing with the callback registered to it.
	 */
	int paCallbackFun(const void *inputBuffer, void *outputBuffer,
	                  unsigned long numFrames,
	                  const PaStreamCallbackTimeInfo *timeInfo,
	                  PaStreamCallbackFlags statusFlags) override;
	PlayCallbackStepResult PlayCallbackStep(char *out,
	                                        unsigned long frames_per_buf,
	                                        PlayCallbackStepResult in);
	PlayCallbackStepResult PlayCallbackSuccess(char *out,
	                                           unsigned long avail,
	                                           unsigned long frames_per_buf,
	                                           PlayCallbackStepResult in);
	PlayCallbackStepResult PlayCallbackFailure(char *out,
	                                           unsigned long avail,
	                                           unsigned long frames_per_buf,
	                                           PlayCallbackStepResult in);

	/**
	 * Reads from the ringbuffer to output, updating the used samples count.
	 * @param output A reference to the output buffer's current pointer.
	 * @param output_capacity The capacity of the output buffer, in samples.
	 * @param buffered_count The number of samples available in the ring
	 *   buffer.
	 * @return The number of samples successfully written to the output
	 *   buffer.
	 */
	unsigned long ReadSamplesToOutput(char *&output,
	                                  unsigned long output_capacity,
	                                  unsigned long buffered_count);

	/**
	 * Decode the next frame if the current frame has been fully used.
	 * @return True if there were some samples left to decode; false
	 *   otherwise.
	 */
	bool DecodeIfFrameEmpty();

	//
	// Ring buffer
	//

	/**
	 * Writes all samples currently waiting to be transferred to the ring
	 * buffer.
	 */
	void WriteAllAvailableToRingBuffer();

	/**
	 * Write a given number of samples from the current frame to the ring
	 * buffer.
	 * @param sample_count  The number of samples to write to the ring
	 *                      buffer.
	 */
	void WriteToRingBuffer(std::uint64_t sample_count);

	/**
	 * The current write capacity of the ring buffer.
	 * @return The write capacity, in samples.
	 */
	std::uint64_t RingBufferWriteCapacity();

	/**
	 * The current read capacity of the ring buffer.
	 * @return The read capacity, in samples.
	 */
	std::uint64_t RingBufferReadCapacity();

	/**
	 * The number of samples that may currently be placed in the ringbuffer.
	 * the ring buffer.
	 * @return The transfer count, in samples.
	 */
	std::uint64_t RingBufferTransferCount();

	/**
	 * Moves the decoded data iterator forwards by a number of samples.
	 *
	 * If the iterator runs off the end of the decoded data vector, the data
	 * vector is freed and set to nullptr, so that a new decoding run can
	 * occur.
	 *
	 * @param sample_count The number of samples to move the markers.
	 */
	void AdvanceFrameIterator(std::uint64_t sample_count);
};

#endif // PS_AUDIO_OUTPUT_HPP
<commit_msg>Remove SPINUP_SIZE.<commit_after>// This file is part of Playslave-C++.
// Playslave-C++ is licenced under the MIT license: see LICENSE.txt.

/**
 * @file
 * Declaration of the AudioOutput class.
 * @see audio/audio_output.cpp
 */

#ifndef PS_AUDIO_OUTPUT_HPP
#define PS_AUDIO_OUTPUT_HPP

#include <chrono>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "portaudio.h"
#include "portaudiocpp/CallbackInterface.hxx"
namespace portaudio {
class Stream;
}

template <typename RepT, typename SampleCountT>
class RingBuffer;

#include "audio_decoder.hpp"
#include "audio_resample.hpp"

/// Type of results emitted during the play callback step.
using PlayCallbackStepResult = std::pair<PaStreamCallbackResult, unsigned long>;

/**
 * Abstract class for objects that can configure PortAudio streams for audio
 * files.
 */
class StreamConfigurator {
public:
	/**
	 * Configures and returns a PortAudio stream for the given decoder.
	 * @param cb The object that PortAudio will call to receive audio.
	 * @param decoder The decoder whose output will be fed into the stream.
	 * @return The configured PortAudio stream.
	 */
	virtual portaudio::Stream *Configure(
	                portaudio::CallbackInterface &cb,
	                const AudioDecoder &decoder) const = 0;
};

/**
 * An audio file and its associated decoder, ringbuffer and output stream.
 *
 * AudioOutput contains all state pertaining to the output of one file to one
 * stream.  It contains an AudioDecoder, a RingBuffer, and implements the
 * portaudio::CallbackInterface (allowing it to send PortAudio decoded audio)
 * and SampleByteConverter (allowing it to be queried for conversions from
 * sample counts to byte counts).
 */
class AudioOutput : portaudio::CallbackInterface, SampleByteConverter {
public:
	/**
	 * Loads a file and constructs an AudioOutput for it.
	 * @param path The absolute path to the file to open.
	 * @param c An object that can configure PortAudio streams.  This will
	 *   usually be the AudioSystem.
	 * @see AudioSystem::Load
	 */
	AudioOutput(const std::string &path, const StreamConfigurator &c);
	~AudioOutput();

	/**
	 * Starts the audio stream.
	 * @see Stop
	 * @see IsHalted
	 */
	void Start();

	/**
	 * Stops the audio stream.
	 * @see Start
	 * @see IsHalted
	 */
	void Stop();

	/**
	 * Performs an update cycle on this AudioOutput.
	 * This ensures the ring buffer has output to offer to the sound driver.
	 * It does this by by asking the AudioDecoder to decode if necessary.
	 * @return True if there is more output to send to the sound card; false
	 *   otherwise.
	 */
	bool Update();

	/**
	 * Checks to see if audio playback has stopped.
	 * @return True if the audio stream is inactive; false otherwise.
	 * @see Start
	 * @see Stop
	 */
	bool IsStopped();

	/**
	 * Returns whether the current frame has been finished.
	 * If this is true, then either the frame is empty, or all of the
	 * samples in the frame have been fed to the ringbuffer.
	 * @return  True if the frame is finished; false otherwise.
	 */
	bool FrameFinished();

	/**
	 * Returns whether the audio file has ended.
	 * This does NOT mean that playback has ended; the ring buffer may still
	 * have samples waiting to send to the audio library.
	 * @return  True if there is no audio left to decode; false otherwise.
	 */
	bool FileEnded();

	/**
	 * Return the current position, as a std::chrono::duration.
	 * @return The current position in the audio.
	 */
	template <typename R>
	R CurrentPosition()
	{
		return std::chrono::duration_cast<R>(
		                CurrentPositionMicroseconds());
	}

	/**
	 * Gets the current played position in the song, in microseconds.
	 * As this may be executing whilst the playing callback is running,
	 * do not expect it to be highly accurate.
	 * @return The current position, in microseconds.
	 */
	std::chrono::microseconds CurrentPositionMicroseconds();

	/**
	 * Seek to a position expressed as a std::chrono::duration.
	 * @param position The position to seek to in the audio.
	 */
	template <typename R>
	void SeekToPosition(R position)
	{
		SeekToPositionMicroseconds(std::chrono::duration_cast<
		                std::chrono::microseconds>(position));
	}

	/**
	 * Attempts to seek to the given position in microseconds.
	 * @param microseconds The position to seek to, in microseconds.
	 */
	void SeekToPositionMicroseconds(std::chrono::microseconds microseconds);

private:
	// Type for the ring buffer.
	using RingBuf = RingBuffer<char, std::uint64_t>;

	/// n, where 2^n is the capacity of the AudioOutput ring buffer.
	/// @see RINGBUF_SIZE
	static const size_t RINGBUF_POWER;

	bool file_ended; ///< Whether the current file has stopped decoding.

	/// The audio decoder providing the actual audio data.
	std::unique_ptr<AudioDecoder> av;

	/// The current decoded frame.
	std::vector<char> frame;

	/// The current position in the current decoded frame.
	std::vector<char>::iterator frame_iterator;

	/// The ring buffer used to transfer samples to the playing callback.
	std::unique_ptr<RingBuf> ring_buf;

	/// The PortAudio stream to which this AudioOutput outputs.
	std::unique_ptr<portaudio::Stream> out_strm;

	/// The current position, in samples.
	uint64_t position_sample_count;

	/**
	 * Clears the current frame and its iterator.
	 */
	void ClearFrame();

	std::uint64_t ByteCountForSampleCount(
	                std::uint64_t sample_count) const override;
	std::uint64_t SampleCountForByteCount(
	                std::uint64_t sample_count) const override;

	/**
	 * The callback proper.
	 * This is executed in a separate thread by PortAudio once a stream is
	 * playing with the callback registered to it.
	 */
	int paCallbackFun(const void *inputBuffer, void *outputBuffer,
	                  unsigned long numFrames,
	                  const PaStreamCallbackTimeInfo *timeInfo,
	                  PaStreamCallbackFlags statusFlags) override;
	PlayCallbackStepResult PlayCallbackStep(char *out,
	                                        unsigned long frames_per_buf,
	                                        PlayCallbackStepResult in);
	PlayCallbackStepResult PlayCallbackSuccess(char *out,
	                                           unsigned long avail,
	                                           unsigned long frames_per_buf,
	                                           PlayCallbackStepResult in);
	PlayCallbackStepResult PlayCallbackFailure(char *out,
	                                           unsigned long avail,
	                                           unsigned long frames_per_buf,
	                                           PlayCallbackStepResult in);

	/**
	 * Reads from the ringbuffer to output, updating the used samples count.
	 * @param output A reference to the output buffer's current pointer.
	 * @param output_capacity The capacity of the output buffer, in samples.
	 * @param buffered_count The number of samples available in the ring
	 *   buffer.
	 * @return The number of samples successfully written to the output
	 *   buffer.
	 */
	unsigned long ReadSamplesToOutput(char *&output,
	                                  unsigned long output_capacity,
	                                  unsigned long buffered_count);

	/**
	 * Decode the next frame if the current frame has been fully used.
	 * @return True if there were some samples left to decode; false
	 *   otherwise.
	 */
	bool DecodeIfFrameEmpty();

	//
	// Ring buffer
	//

	/**
	 * Writes all samples currently waiting to be transferred to the ring
	 * buffer.
	 */
	void WriteAllAvailableToRingBuffer();

	/**
	 * Write a given number of samples from the current frame to the ring
	 * buffer.
	 * @param sample_count  The number of samples to write to the ring
	 *                      buffer.
	 */
	void WriteToRingBuffer(std::uint64_t sample_count);

	/**
	 * The current write capacity of the ring buffer.
	 * @return The write capacity, in samples.
	 */
	std::uint64_t RingBufferWriteCapacity();

	/**
	 * The current read capacity of the ring buffer.
	 * @return The read capacity, in samples.
	 */
	std::uint64_t RingBufferReadCapacity();

	/**
	 * The number of samples that may currently be placed in the ringbuffer.
	 * the ring buffer.
	 * @return The transfer count, in samples.
	 */
	std::uint64_t RingBufferTransferCount();

	/**
	 * Moves the decoded data iterator forwards by a number of samples.
	 *
	 * If the iterator runs off the end of the decoded data vector, the data
	 * vector is freed and set to nullptr, so that a new decoding run can
	 * occur.
	 *
	 * @param sample_count The number of samples to move the markers.
	 */
	void AdvanceFrameIterator(std::uint64_t sample_count);
};

#endif // PS_AUDIO_OUTPUT_HPP
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile: mitkPropertyManager.cpp,v $
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#include <assert.h>
#include <queue>
#include <ipPic/ipPicTypeMultiplex.h>
#include "ipSegmentation.h"

/*
Starts a 4 neighbourhood region growing at startOfs (y*picWidth+x) of the 2D image src.
If relativeBounds is true, the region grows in [base-lowerBound, base+upperBound], in which base is the average
color of the 9 pixels around startOfs. If relativeBounds is false, the region grows in [lowerBound, upperBound].
If maxIterations is > 0, the growing process is stopped after maxIterations.
If segBuffer is 0, new memory for the segmented image is allocated and returned, else the segBuffer is used
to store the result (has to be an 8-bit datatype, e.g. ipUInt1_t).
histBuffer must be 0 or a pointer to a 16-bit ipUInt1_t image of the same size as src. In case of the latter,
history data is written to that buffer: the seed pixel gets a 1, all direct neighbours 2 etc. The buffer is
not cleared in this function and can thus hold history data of several growing processes in different areas.
*/
template<typename PicType>
ipPicDescriptor*
tmGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBoundFlt, float upperBoundFlt, int maxIterations, ipPicDescriptor *segBuffer, int &contourOfs, float &startCol, ipPicDescriptor *histBuffer )
{
  PicType lowerBound = static_cast<PicType>(lowerBoundFlt);
  PicType upperBound = static_cast<PicType>(upperBoundFlt);
  std::queue<int> ofsQueue;

  if (maxIterations <= 0) maxIterations = 32000;
  if (!src) return 0;
  if (!segBuffer) {
    segBuffer = ipPicCopyHeader( src, segBuffer );
    segBuffer->type = ipPicUInt;
    segBuffer->bpe = 8;
    ipUInt4_t size = _ipPicSize( segBuffer );
    segBuffer->data = malloc( size );
  }
  else {
    // check if dimension of segBuffer is valid, if not: change it!
    if (segBuffer->n[0] != src->n[0] || segBuffer->n[1] != src->n[1]) {
      segBuffer->n[0] = src->n[0];
      segBuffer->n[1] = src->n[1];
      ipUInt4_t size = _ipPicSize( segBuffer );
      segBuffer->data = realloc( segBuffer->data, size );
      if (segBuffer->data == 0) return 0;
    }
  }
  if (histBuffer) {
    // check if dimension of histBuffer is valid, if not: change it!
    if (histBuffer->n[0] != src->n[0] || histBuffer->n[1] != src->n[1]) {
      histBuffer->n[0] = src->n[0];
      histBuffer->n[1] = src->n[1];
      ipUInt4_t size = _ipPicSize( histBuffer );
      histBuffer->data = realloc( histBuffer->data, size );
      if (histBuffer->data == 0) return 0;
      memset( histBuffer->data, 0, size );  // clear buffer
    }
  }

  int line = segBuffer->n[0];
  int maxOfs = (int)(line * segBuffer->n[1]);
  //PicType *start = ((PicType*)src->data) + startOfs;
  // init borders:
  PicType lowest, highest;
  if (relativeBounds) {

    // average base color from 3x3 block:
    // check for edges of image
    int offset;
    int numberOfValidOffsets = 0;
    PicType baseCol = 0;
    offset = startOfs;           if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1;         if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1-line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-line;      if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1-line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1;         if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1+line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+line;      if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1+line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }

    if ( numberOfValidOffsets > 0 )
      baseCol = (PicType)( (float)baseCol / (float)numberOfValidOffsets );

    lowest = baseCol - lowerBound;
    highest = baseCol + upperBound;
    startCol = (float)baseCol;
  }
  else {
    lowest = lowerBound;
    highest = upperBound;
    startCol = 0.0f;
  }

  memset( segBuffer->data, 0, _ipPicSize(segBuffer) );  // clear buffer

  PicType value = *((PicType*)src->data+startOfs);
  if ( value >=lowest && value <=highest ) {
    ofsQueue.push( startOfs );
  }

  contourOfs = -1;
  int testOfs;
  ipUInt1_t segVal;
  int iteration = 0;
  int currentWave = 1;
  int nextWave = 0;

  while (!ofsQueue.empty() && iteration<=maxIterations) {
    int nextOfs = ofsQueue.front();
    ofsQueue.pop();
    currentWave--;
    *((ipUInt1_t*)segBuffer->data+nextOfs) = 1;
    if (histBuffer) {
      *((ipUInt2_t*)histBuffer->data+nextOfs) = (ipUInt2_t)(iteration+1);  // seed point should get history = 1
    }
    if (nextOfs > contourOfs) contourOfs = nextOfs;
    // check right:
    testOfs = nextOfs+1;
    if (testOfs%line!=0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check top:
    testOfs = nextOfs-line;
    if (testOfs > 0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check left:
    testOfs = nextOfs-1;
    if (nextOfs%line!=0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check bottom:
    testOfs = nextOfs+line;
    if (testOfs < maxOfs) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check for number of iterations:
    if (currentWave == 0) {
      currentWave = nextWave;
      nextWave = 0;
      iteration++;
    }
  }

  return segBuffer;
}

ipPicDescriptor*
ipMITKSegmentationGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBound, float upperBound, int maxIterations, ipPicDescriptor *segBuffer, ipPicDescriptor *histBuffer )
{
  ipPicDescriptor *result = 0;
  int contourOfs;
  float startCol;

  if (ipMITKSegmentationUndoIsEnabled (segBuffer)) {
    ipMITKSegmentationUndoSave (segBuffer);
  }

  mitkIpPicTypeMultiplexR9( tmGrowRegion4N, src, result, startOfs, relativeBounds, lowerBound, upperBound, maxIterations, segBuffer, contourOfs, startCol, histBuffer );
  return result;
}

ipPicDescriptor*
ipMITKSegmentationGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBound, float upperBound, int maxIterations, ipPicDescriptor *segBuffer, int &contourOfs, float &startCol, ipPicDescriptor *histBuffer )
{
  ipPicDescriptor *result = 0;

  if (ipMITKSegmentationUndoIsEnabled (segBuffer)) {
    ipMITKSegmentationUndoSave (segBuffer);
  }

  mitkIpPicTypeMultiplexR9( tmGrowRegion4N, src, result, startOfs, relativeBounds, lowerBound, upperBound, maxIterations, segBuffer, contourOfs, startCol, histBuffer );
  return result;
}
<commit_msg>FIX (#2366): Possible variable overflow in baseCol calculation; changed type to int <commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile: mitkPropertyManager.cpp,v $
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#include <assert.h>
#include <queue>
#include <ipPic/ipPicTypeMultiplex.h>
#include "ipSegmentation.h"

/*
Starts a 4 neighbourhood region growing at startOfs (y*picWidth+x) of the 2D image src.
If relativeBounds is true, the region grows in [base-lowerBound, base+upperBound], in which base is the average
color of the 9 pixels around startOfs. If relativeBounds is false, the region grows in [lowerBound, upperBound].
If maxIterations is > 0, the growing process is stopped after maxIterations.
If segBuffer is 0, new memory for the segmented image is allocated and returned, else the segBuffer is used
to store the result (has to be an 8-bit datatype, e.g. ipUInt1_t).
histBuffer must be 0 or a pointer to a 16-bit ipUInt1_t image of the same size as src. In case of the latter,
history data is written to that buffer: the seed pixel gets a 1, all direct neighbours 2 etc. The buffer is
not cleared in this function and can thus hold history data of several growing processes in different areas.
*/
template<typename PicType>
ipPicDescriptor*
tmGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBoundFlt, float upperBoundFlt, int maxIterations, ipPicDescriptor *segBuffer, int &contourOfs, float &startCol, ipPicDescriptor *histBuffer )
{
  PicType lowerBound = static_cast<PicType>(lowerBoundFlt);
  PicType upperBound = static_cast<PicType>(upperBoundFlt);
  std::queue<int> ofsQueue;

  if (maxIterations <= 0) maxIterations = 32000;
  if (!src) return 0;
  if (!segBuffer) {
    segBuffer = ipPicCopyHeader( src, segBuffer );
    segBuffer->type = ipPicUInt;
    segBuffer->bpe = 8;
    ipUInt4_t size = _ipPicSize( segBuffer );
    segBuffer->data = malloc( size );
  }
  else {
    // check if dimension of segBuffer is valid, if not: change it!
    if (segBuffer->n[0] != src->n[0] || segBuffer->n[1] != src->n[1]) {
      segBuffer->n[0] = src->n[0];
      segBuffer->n[1] = src->n[1];
      ipUInt4_t size = _ipPicSize( segBuffer );
      segBuffer->data = realloc( segBuffer->data, size );
      if (segBuffer->data == 0) return 0;
    }
  }
  if (histBuffer) {
    // check if dimension of histBuffer is valid, if not: change it!
    if (histBuffer->n[0] != src->n[0] || histBuffer->n[1] != src->n[1]) {
      histBuffer->n[0] = src->n[0];
      histBuffer->n[1] = src->n[1];
      ipUInt4_t size = _ipPicSize( histBuffer );
      histBuffer->data = realloc( histBuffer->data, size );
      if (histBuffer->data == 0) return 0;
      memset( histBuffer->data, 0, size );  // clear buffer
    }
  }

  int line = segBuffer->n[0];
  int maxOfs = (int)(line * segBuffer->n[1]);
  //PicType *start = ((PicType*)src->data) + startOfs;
  // init borders:
  PicType lowest, highest;
  if (relativeBounds) {

    // average base color from 3x3 block:
    // check for edges of image
    int offset;
    int numberOfValidOffsets = 0;
    int baseCol = 0;
    offset = startOfs;           if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1;         if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1-line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-line;      if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1-line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1;         if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs-1+line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+line;      if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }
    offset = startOfs+1+line;    if ( (offset >= 0) && (offset < (int)(src->n[0] * src->n[1])) ) { baseCol += *((PicType*)(src->data)+offset); ++numberOfValidOffsets; }

    if ( numberOfValidOffsets > 0 )
      baseCol = (PicType)( (float)baseCol / (float)numberOfValidOffsets );

    lowest = baseCol - lowerBound;
    highest = baseCol + upperBound;
    startCol = (float)baseCol;
  }
  else {
    lowest = lowerBound;
    highest = upperBound;
    startCol = 0.0f;
  }

  memset( segBuffer->data, 0, _ipPicSize(segBuffer) );  // clear buffer

  PicType value = *((PicType*)src->data+startOfs);
  if ( value >=lowest && value <=highest ) {
    ofsQueue.push( startOfs );
  }

  contourOfs = -1;
  int testOfs;
  ipUInt1_t segVal;
  int iteration = 0;
  int currentWave = 1;
  int nextWave = 0;

  while (!ofsQueue.empty() && iteration<=maxIterations) {
    int nextOfs = ofsQueue.front();
    ofsQueue.pop();
    currentWave--;
    *((ipUInt1_t*)segBuffer->data+nextOfs) = 1;
    if (histBuffer) {
      *((ipUInt2_t*)histBuffer->data+nextOfs) = (ipUInt2_t)(iteration+1);  // seed point should get history = 1
    }
    if (nextOfs > contourOfs) contourOfs = nextOfs;
    // check right:
    testOfs = nextOfs+1;
    if (testOfs%line!=0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check top:
    testOfs = nextOfs-line;
    if (testOfs > 0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check left:
    testOfs = nextOfs-1;
    if (nextOfs%line!=0) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check bottom:
    testOfs = nextOfs+line;
    if (testOfs < maxOfs) {
      segVal = *((ipUInt1_t*)segBuffer->data+testOfs);
      if ( segVal == 0 ) {
        value = *((PicType*)src->data+testOfs);
        if ( value >=lowest && value <=highest ) {
          ofsQueue.push( testOfs );
          nextWave++;
          *((ipUInt1_t*)segBuffer->data+testOfs) = 2;
        }
      }
    }
    // check for number of iterations:
    if (currentWave == 0) {
      currentWave = nextWave;
      nextWave = 0;
      iteration++;
    }
  }

  return segBuffer;
}

ipPicDescriptor*
ipMITKSegmentationGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBound, float upperBound, int maxIterations, ipPicDescriptor *segBuffer, ipPicDescriptor *histBuffer )
{
  ipPicDescriptor *result = 0;
  int contourOfs;
  float startCol;

  if (ipMITKSegmentationUndoIsEnabled (segBuffer)) {
    ipMITKSegmentationUndoSave (segBuffer);
  }

  mitkIpPicTypeMultiplexR9( tmGrowRegion4N, src, result, startOfs, relativeBounds, lowerBound, upperBound, maxIterations, segBuffer, contourOfs, startCol, histBuffer );
  return result;
}

ipPicDescriptor*
ipMITKSegmentationGrowRegion4N( ipPicDescriptor *src, int startOfs, bool relativeBounds, float lowerBound, float upperBound, int maxIterations, ipPicDescriptor *segBuffer, int &contourOfs, float &startCol, ipPicDescriptor *histBuffer )
{
  ipPicDescriptor *result = 0;

  if (ipMITKSegmentationUndoIsEnabled (segBuffer)) {
    ipMITKSegmentationUndoSave (segBuffer);
  }

  mitkIpPicTypeMultiplexR9( tmGrowRegion4N, src, result, startOfs, relativeBounds, lowerBound, upperBound, maxIterations, segBuffer, contourOfs, startCol, histBuffer );
  return result;
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS dba09 (1.10.152); FILE MERGED 2004/03/24 10:04:58 fs 1.10.152.2: RESYNC: (1.10-1.11); FILE MERGED 2004/03/22 16:13:59 fs 1.10.152.1: new prop<commit_after><|endoftext|>