<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include "querydescriptor.hxx"
#include "apitools.hxx"
#include "dbastrings.hrc"
#include <comphelper/property.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include "definitioncolumn.hxx"
#include <tools/debug.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::util;
using namespace ::comphelper;
using namespace ::osl;
using namespace ::cppu;

namespace dbaccess
{

//==========================================================================
//= OQueryDescriptor
//==========================================================================
DBG_NAME(OQueryDescriptor)

OQueryDescriptor::OQueryDescriptor()
    :OQueryDescriptor_Base(m_aMutex,*this)
    ,ODataSettings(m_aBHelper,sal_True)
{
    DBG_CTOR(OQueryDescriptor,NULL);
    registerProperties();
    ODataSettings::registerPropertiesFor(this);
}

OQueryDescriptor::OQueryDescriptor(const OQueryDescriptor_Base& _rSource)
    :OQueryDescriptor_Base(_rSource,*this)
    ,ODataSettings(m_aBHelper,sal_True)
{
    DBG_CTOR(OQueryDescriptor,NULL);
    registerProperties();
    ODataSettings::registerPropertiesFor(this);
}

OQueryDescriptor::~OQueryDescriptor()
{
    DBG_DTOR(OQueryDescriptor,NULL);
}

IMPLEMENT_TYPEPROVIDER2(OQueryDescriptor,OQueryDescriptor_Base,ODataSettings);
IMPLEMENT_FORWARD_XINTERFACE3( OQueryDescriptor,OWeakObject,OQueryDescriptor_Base,ODataSettings)

void OQueryDescriptor::registerProperties()
{
    // the properties which OCommandBase supplies (it has no own registration, as it's not derived from
    // a OPropertyStateContainer)
    registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED,
                    &m_sElementName, ::getCppuType(&m_sElementName));

    registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
                    &m_sCommand, ::getCppuType(&m_sCommand));

    registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
                    &m_bEscapeProcessing, ::getBooleanCppuType());

    registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
                    &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName));

    registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
                    &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName));

    registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
                    &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName));

    registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
                    &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation));
}

Reference< XPropertySetInfo > SAL_CALL OQueryDescriptor::getPropertySetInfo(  ) throw(RuntimeException)
{
    return createPropertySetInfo( getInfoHelper() ) ;
}

::cppu::IPropertyArrayHelper& OQueryDescriptor::getInfoHelper()
{
    return *getArrayHelper();
}

::cppu::IPropertyArrayHelper* OQueryDescriptor::createArrayHelper( ) const
{
    Sequence< Property > aProps;
    describeProperties(aProps);
    return new ::cppu::OPropertyArrayHelper(aProps);
}

DBG_NAME(OQueryDescriptor_Base);

OQueryDescriptor_Base::OQueryDescriptor_Base(::osl::Mutex&  _rMutex,::cppu::OWeakObject& _rMySelf)
    :m_bColumnsOutOfDate(sal_True)
    ,m_rMutex(_rMutex)
{
    DBG_CTOR(OQueryDescriptor_Base,NULL);
    m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this);
}

OQueryDescriptor_Base::OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf)
    :m_bColumnsOutOfDate(sal_True)
    ,m_rMutex(_rSource.m_rMutex)
{
    DBG_CTOR(OQueryDescriptor_Base,NULL);
    m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this);

    m_sCommand = _rSource.m_sCommand;
    m_bEscapeProcessing = _rSource.m_bEscapeProcessing;
    m_sUpdateTableName = _rSource.m_sUpdateTableName;
    m_sUpdateSchemaName = _rSource.m_sUpdateSchemaName;
    m_sUpdateCatalogName = _rSource.m_sUpdateCatalogName;
    m_aLayoutInformation = _rSource.m_aLayoutInformation;
}

OQueryDescriptor_Base::~OQueryDescriptor_Base()
{
    m_pColumns->acquire();
    m_pColumns->disposing();
    delete m_pColumns;

    DBG_DTOR(OQueryDescriptor_Base,NULL);
}

sal_Int64 SAL_CALL OQueryDescriptor_Base::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException)
{
    if (_rIdentifier.getLength() != 16)
        return 0;

    if (0 == rtl_compareMemory(getImplementationId().getConstArray(),  _rIdentifier.getConstArray(), 16 ) )
        return reinterpret_cast<sal_Int64>(this);

    return 0;
}

IMPLEMENT_IMPLEMENTATION_ID(OQueryDescriptor_Base)

void OQueryDescriptor_Base::setColumnsOutOfDate( sal_Bool _bOutOfDate )
{
    m_bColumnsOutOfDate = _bOutOfDate;
    if ( !m_bColumnsOutOfDate )
        m_pColumns->setInitialized();
}

void OQueryDescriptor_Base::implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn )
{
    m_pColumns->append( _rName, _pColumn );
}

void OQueryDescriptor_Base::clearColumns( )
{
    m_pColumns->clearColumns();

    setColumnsOutOfDate();
}

Reference< XNameAccess > SAL_CALL OQueryDescriptor_Base::getColumns( ) throw (RuntimeException)
{
    MutexGuard aGuard(m_rMutex);

    if ( isColumnsOutOfDate() )
    {
        // clear the current columns
        clearColumns();

        // do this before rebuildColumns. This prevents recursion, e.g. in the case where we
        // have queries with cyclic references:
        // foo := SELECT * FROM bar
        // bar := SELECT * FROM foo
        setColumnsOutOfDate( sal_False );

        // rebuild them
        try
        {
            rebuildColumns();
        }
        catch ( const Exception& )
        {
            setColumnsOutOfDate( sal_True );
            throw;
        }
    }

    return m_pColumns;
}

::rtl::OUString SAL_CALL OQueryDescriptor_Base::getImplementationName(  ) throw(RuntimeException)
{
    return ::rtl::OUString::createFromAscii("com.sun.star.sdb.OQueryDescriptor");
}

sal_Bool SAL_CALL OQueryDescriptor_Base::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
{
    return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
}

Sequence< ::rtl::OUString > SAL_CALL OQueryDescriptor_Base::getSupportedServiceNames(  ) throw(RuntimeException)
{
    Sequence< ::rtl::OUString > aSupported(2);
    aSupported.getArray()[0] = SERVICE_SDB_DATASETTINGS;
    aSupported.getArray()[1] = SERVICE_SDB_QUERYDESCRIPTOR;
    return aSupported;
}

void OQueryDescriptor_Base::disposeColumns()
{
    m_pColumns->disposing();
}

void OQueryDescriptor_Base::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ )
{
    // not interested in
}

void OQueryDescriptor_Base::columnDropped(const ::rtl::OUString& /*_sName*/)
{
    // not interested in
}

Reference< XPropertySet > OQueryDescriptor_Base::createColumnDescriptor()
{
    OSL_ENSURE( false, "OQueryDescriptor_Base::createColumnDescriptor: called why?" );
    return NULL;
}

void OQueryDescriptor_Base::rebuildColumns( )
{
}

// IRefreshableColumns
void OQueryDescriptor_Base::refreshColumns()
{
    MutexGuard aGuard( m_rMutex );

    clearColumns();
    rebuildColumns();
}

OColumn* OQueryDescriptor_Base::createColumn( const ::rtl::OUString& /*_rName*/ ) const
{
    // creating a column/descriptor for a query/descriptor does not make sense at all
    return NULL;
}

<<<<<<< HEAD
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
=======
}   // namespace dbaccess
>>>>>>> Removed comments, trailing spaces and death code
<commit_msg>remove conflict markers<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include "querydescriptor.hxx"
#include "apitools.hxx"
#include "dbastrings.hrc"
#include <comphelper/property.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include "definitioncolumn.hxx"
#include <tools/debug.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::util;
using namespace ::comphelper;
using namespace ::osl;
using namespace ::cppu;

namespace dbaccess
{

//==========================================================================
//= OQueryDescriptor
//==========================================================================
DBG_NAME(OQueryDescriptor)

OQueryDescriptor::OQueryDescriptor()
    :OQueryDescriptor_Base(m_aMutex,*this)
    ,ODataSettings(m_aBHelper,sal_True)
{
    DBG_CTOR(OQueryDescriptor,NULL);
    registerProperties();
    ODataSettings::registerPropertiesFor(this);
}

OQueryDescriptor::OQueryDescriptor(const OQueryDescriptor_Base& _rSource)
    :OQueryDescriptor_Base(_rSource,*this)
    ,ODataSettings(m_aBHelper,sal_True)
{
    DBG_CTOR(OQueryDescriptor,NULL);
    registerProperties();
    ODataSettings::registerPropertiesFor(this);
}

OQueryDescriptor::~OQueryDescriptor()
{
    DBG_DTOR(OQueryDescriptor,NULL);
}

IMPLEMENT_TYPEPROVIDER2(OQueryDescriptor,OQueryDescriptor_Base,ODataSettings);
IMPLEMENT_FORWARD_XINTERFACE3( OQueryDescriptor,OWeakObject,OQueryDescriptor_Base,ODataSettings)

void OQueryDescriptor::registerProperties()
{
    // the properties which OCommandBase supplies (it has no own registration, as it's not derived from
    // a OPropertyStateContainer)
    registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED,
                    &m_sElementName, ::getCppuType(&m_sElementName));

    registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
                    &m_sCommand, ::getCppuType(&m_sCommand));

    registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
                    &m_bEscapeProcessing, ::getBooleanCppuType());

    registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
                    &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName));

    registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
                    &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName));

    registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
                    &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName));

    registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
                    &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation));
}

Reference< XPropertySetInfo > SAL_CALL OQueryDescriptor::getPropertySetInfo(  ) throw(RuntimeException)
{
    return createPropertySetInfo( getInfoHelper() ) ;
}

::cppu::IPropertyArrayHelper& OQueryDescriptor::getInfoHelper()
{
    return *getArrayHelper();
}

::cppu::IPropertyArrayHelper* OQueryDescriptor::createArrayHelper( ) const
{
    Sequence< Property > aProps;
    describeProperties(aProps);
    return new ::cppu::OPropertyArrayHelper(aProps);
}

DBG_NAME(OQueryDescriptor_Base);

OQueryDescriptor_Base::OQueryDescriptor_Base(::osl::Mutex&  _rMutex,::cppu::OWeakObject& _rMySelf)
    :m_bColumnsOutOfDate(sal_True)
    ,m_rMutex(_rMutex)
{
    DBG_CTOR(OQueryDescriptor_Base,NULL);
    m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this);
}

OQueryDescriptor_Base::OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf)
    :m_bColumnsOutOfDate(sal_True)
    ,m_rMutex(_rSource.m_rMutex)
{
    DBG_CTOR(OQueryDescriptor_Base,NULL);
    m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this);

    m_sCommand = _rSource.m_sCommand;
    m_bEscapeProcessing = _rSource.m_bEscapeProcessing;
    m_sUpdateTableName = _rSource.m_sUpdateTableName;
    m_sUpdateSchemaName = _rSource.m_sUpdateSchemaName;
    m_sUpdateCatalogName = _rSource.m_sUpdateCatalogName;
    m_aLayoutInformation = _rSource.m_aLayoutInformation;
}

OQueryDescriptor_Base::~OQueryDescriptor_Base()
{
    m_pColumns->acquire();
    m_pColumns->disposing();
    delete m_pColumns;

    DBG_DTOR(OQueryDescriptor_Base,NULL);
}

sal_Int64 SAL_CALL OQueryDescriptor_Base::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException)
{
    if (_rIdentifier.getLength() != 16)
        return 0;

    if (0 == rtl_compareMemory(getImplementationId().getConstArray(),  _rIdentifier.getConstArray(), 16 ) )
        return reinterpret_cast<sal_Int64>(this);

    return 0;
}

IMPLEMENT_IMPLEMENTATION_ID(OQueryDescriptor_Base)

void OQueryDescriptor_Base::setColumnsOutOfDate( sal_Bool _bOutOfDate )
{
    m_bColumnsOutOfDate = _bOutOfDate;
    if ( !m_bColumnsOutOfDate )
        m_pColumns->setInitialized();
}

void OQueryDescriptor_Base::implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn )
{
    m_pColumns->append( _rName, _pColumn );
}

void OQueryDescriptor_Base::clearColumns( )
{
    m_pColumns->clearColumns();

    setColumnsOutOfDate();
}

Reference< XNameAccess > SAL_CALL OQueryDescriptor_Base::getColumns( ) throw (RuntimeException)
{
    MutexGuard aGuard(m_rMutex);

    if ( isColumnsOutOfDate() )
    {
        // clear the current columns
        clearColumns();

        // do this before rebuildColumns. This prevents recursion, e.g. in the case where we
        // have queries with cyclic references:
        // foo := SELECT * FROM bar
        // bar := SELECT * FROM foo
        setColumnsOutOfDate( sal_False );

        // rebuild them
        try
        {
            rebuildColumns();
        }
        catch ( const Exception& )
        {
            setColumnsOutOfDate( sal_True );
            throw;
        }
    }

    return m_pColumns;
}

::rtl::OUString SAL_CALL OQueryDescriptor_Base::getImplementationName(  ) throw(RuntimeException)
{
    return ::rtl::OUString::createFromAscii("com.sun.star.sdb.OQueryDescriptor");
}

sal_Bool SAL_CALL OQueryDescriptor_Base::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
{
    return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
}

Sequence< ::rtl::OUString > SAL_CALL OQueryDescriptor_Base::getSupportedServiceNames(  ) throw(RuntimeException)
{
    Sequence< ::rtl::OUString > aSupported(2);
    aSupported.getArray()[0] = SERVICE_SDB_DATASETTINGS;
    aSupported.getArray()[1] = SERVICE_SDB_QUERYDESCRIPTOR;
    return aSupported;
}

void OQueryDescriptor_Base::disposeColumns()
{
    m_pColumns->disposing();
}

void OQueryDescriptor_Base::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ )
{
    // not interested in
}

void OQueryDescriptor_Base::columnDropped(const ::rtl::OUString& /*_sName*/)
{
    // not interested in
}

Reference< XPropertySet > OQueryDescriptor_Base::createColumnDescriptor()
{
    OSL_ENSURE( false, "OQueryDescriptor_Base::createColumnDescriptor: called why?" );
    return NULL;
}

void OQueryDescriptor_Base::rebuildColumns( )
{
}

// IRefreshableColumns
void OQueryDescriptor_Base::refreshColumns()
{
    MutexGuard aGuard( m_rMutex );

    clearColumns();
    rebuildColumns();
}

OColumn* OQueryDescriptor_Base::createColumn( const ::rtl::OUString& /*_rName*/ ) const
{
    // creating a column/descriptor for a query/descriptor does not make sense at all
    return NULL;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>//
//  AsyncTaskQueue.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/10/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef AsyncTaskQueue_hpp
#define AsyncTaskQueue_hpp

#include <atomic>
#include <condition_variable>
#include <functional>
#include <thread>
#include <vector>

#include "../ClockReceiver/TimeTypes.hpp"

#if defined(__APPLE__) && !defined(IGNORE_APPLE)
#include <dispatch/dispatch.h>
#define USE_GCD
#endif

namespace Concurrency {

/// An implementation detail; provides the time-centric part of a TaskQueue with a real Performer.
template <typename Performer> struct TaskQueueStorage {
	template <typename... Args> TaskQueueStorage(Args&&... args) :
		performer(std::forward<Args>(args)...),
		last_fired_(Time::nanos_now()) {}

	Performer performer;

	protected:
		void update() {
			auto time_now = Time::nanos_now();
			performer.perform(time_now - last_fired_);
			last_fired_ = time_now;
		}

	private:
		Time::Nanos last_fired_;
};

/// An implementation detail; provides a no-op implementation of time advances for TaskQueues without a Performer.
template <> struct TaskQueueStorage<int> {
	TaskQueueStorage() {}

	protected:
		void update() {}
};

/*!
	A task queue allows a caller to enqueue void(void) functions. Those functions are guaranteed
	to be performed serially and asynchronously from the caller.

	If @c perform_automatically is true, functions will be performed as soon as is possible,
	at the cost of thread synchronisation.

	If @c perform_automatically is false, functions will be queued up and not dispatched
	until a call to perform().

	If a @c Performer type is supplied then a public member, @c performer will be constructed
	with the arguments supplied to TaskQueue's constructor, and that class will receive  calls of the
	form @c .perform(nanos) to update it to every batch of new actions.
*/
template <bool perform_automatically, typename Performer = int> class TaskQueue: public TaskQueueStorage<Performer> {
	public:
		template <typename... Args> TaskQueue(Args&&... args) :
			TaskQueueStorage<Performer>(std::forward<Args>(args)...),
			thread_{
				[this] {
					ActionVector actions;

					while(!should_quit) {
						// Wait for new actions to be signalled, and grab them.
						std::unique_lock lock(condition_mutex_);
						while(actions_.empty()) {
							condition_.wait(lock);
						}
						std::swap(actions, actions_);
						lock.unlock();

						// Update to now (which is possibly a no-op).
						TaskQueueStorage<Performer>::update();

						// Perform the actions and destroy them.
						for(const auto &action: actions) {
							action();
						}
						actions.clear();
					}
				}
			} {}

		/// Enqueus @c post_action to be performed asynchronously at some point
		/// in the future. If @c perform_automatically is @c true then the action
		/// will be performed as soon as possible. Otherwise it will sit unsheculed until
		/// a call to @c perform().
		///
		/// Actions may be elided.
		///
		/// If this TaskQueue has a @c Performer then the action will be performed
		/// on the same thread as the performer, after the performer has been updated
		/// to 'now'.
		void enqueue(const std::function<void(void)> &post_action) {
			std::lock_guard guard(condition_mutex_);
			actions_.push_back(post_action);

			if constexpr (perform_automatically) {
				condition_.notify_all();
			}
		}

		/// Causes any enqueued actions that are not yet scheduled to be scheduled.
		void perform() {
			if(actions_.empty()) {
				return;
			}
			condition_.notify_all();
		}

		/// Permanently stops this task queue, blocking until that has happened.
		/// All pending actions will be performed first.
		///
		/// The queue cannot be restarted; this is a destructive action.
		void stop() {
			if(thread_.joinable()) {
				should_quit = true;
				enqueue([] {});
				if constexpr (!perform_automatically) {
					perform();
				}
				thread_.join();
			}
		}

		/// Schedules any remaining unscheduled work, then blocks synchronously
		/// until all scheduled work has been performed.
		void flush() {
			std::mutex flush_mutex;
			std::condition_variable flush_condition;
			bool has_run = false;
			std::unique_lock lock(flush_mutex);

			enqueue([&flush_mutex, &flush_condition, &has_run] () {
				std::unique_lock inner_lock(flush_mutex);
				has_run = true;
				flush_condition.notify_all();
			});

			if constexpr (!perform_automatically) {
				perform();
			}

			flush_condition.wait(lock, [&has_run] { return has_run; });
		}

		~TaskQueue() {
			stop();
		}

	private:
		// The list of actions waiting be performed. These will be elided,
		// increasing their latency, if the emulation thread falls behind.
		using ActionVector = std::vector<std::function<void(void)>>;
		ActionVector actions_;

		// Necessary synchronisation parts.
		std::atomic<bool> should_quit = false;
		std::mutex condition_mutex_;
		std::condition_variable condition_;

		// Ensure the thread isn't constructed until after the mutex
		// and condition variable.
		std::thread thread_;
};

}

#endif /* AsyncTaskQueue_hpp */
<commit_msg>Fix variable name.<commit_after>//
//  AsyncTaskQueue.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/10/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef AsyncTaskQueue_hpp
#define AsyncTaskQueue_hpp

#include <atomic>
#include <condition_variable>
#include <functional>
#include <thread>
#include <vector>

#include "../ClockReceiver/TimeTypes.hpp"

#if defined(__APPLE__) && !defined(IGNORE_APPLE)
#include <dispatch/dispatch.h>
#define USE_GCD
#endif

namespace Concurrency {

/// An implementation detail; provides the time-centric part of a TaskQueue with a real Performer.
template <typename Performer> struct TaskQueueStorage {
	template <typename... Args> TaskQueueStorage(Args&&... args) :
		performer(std::forward<Args>(args)...),
		last_fired_(Time::nanos_now()) {}

	Performer performer;

	protected:
		void update() {
			auto time_now = Time::nanos_now();
			performer.perform(time_now - last_fired_);
			last_fired_ = time_now;
		}

	private:
		Time::Nanos last_fired_;
};

/// An implementation detail; provides a no-op implementation of time advances for TaskQueues without a Performer.
template <> struct TaskQueueStorage<int> {
	TaskQueueStorage() {}

	protected:
		void update() {}
};

/*!
	A task queue allows a caller to enqueue void(void) functions. Those functions are guaranteed
	to be performed serially and asynchronously from the caller.

	If @c perform_automatically is true, functions will be performed as soon as is possible,
	at the cost of thread synchronisation.

	If @c perform_automatically is false, functions will be queued up and not dispatched
	until a call to perform().

	If a @c Performer type is supplied then a public member, @c performer will be constructed
	with the arguments supplied to TaskQueue's constructor, and that class will receive  calls of the
	form @c .perform(nanos) to update it to every batch of new actions.
*/
template <bool perform_automatically, typename Performer = int> class TaskQueue: public TaskQueueStorage<Performer> {
	public:
		template <typename... Args> TaskQueue(Args&&... args) :
			TaskQueueStorage<Performer>(std::forward<Args>(args)...),
			thread_{
				[this] {
					ActionVector actions;

					while(!should_quit_) {
						// Wait for new actions to be signalled, and grab them.
						std::unique_lock lock(condition_mutex_);
						while(actions_.empty()) {
							condition_.wait(lock);
						}
						std::swap(actions, actions_);
						lock.unlock();

						// Update to now (which is possibly a no-op).
						TaskQueueStorage<Performer>::update();

						// Perform the actions and destroy them.
						for(const auto &action: actions) {
							action();
						}
						actions.clear();
					}
				}
			} {}

		/// Enqueus @c post_action to be performed asynchronously at some point
		/// in the future. If @c perform_automatically is @c true then the action
		/// will be performed as soon as possible. Otherwise it will sit unsheculed until
		/// a call to @c perform().
		///
		/// Actions may be elided.
		///
		/// If this TaskQueue has a @c Performer then the action will be performed
		/// on the same thread as the performer, after the performer has been updated
		/// to 'now'.
		void enqueue(const std::function<void(void)> &post_action) {
			std::lock_guard guard(condition_mutex_);
			actions_.push_back(post_action);

			if constexpr (perform_automatically) {
				condition_.notify_all();
			}
		}

		/// Causes any enqueued actions that are not yet scheduled to be scheduled.
		void perform() {
			if(actions_.empty()) {
				return;
			}
			condition_.notify_all();
		}

		/// Permanently stops this task queue, blocking until that has happened.
		/// All pending actions will be performed first.
		///
		/// The queue cannot be restarted; this is a destructive action.
		void stop() {
			if(thread_.joinable()) {
				should_quit_ = true;
				enqueue([] {});
				if constexpr (!perform_automatically) {
					perform();
				}
				thread_.join();
			}
		}

		/// Schedules any remaining unscheduled work, then blocks synchronously
		/// until all scheduled work has been performed.
		void flush() {
			std::mutex flush_mutex;
			std::condition_variable flush_condition;
			bool has_run = false;
			std::unique_lock lock(flush_mutex);

			enqueue([&flush_mutex, &flush_condition, &has_run] () {
				std::unique_lock inner_lock(flush_mutex);
				has_run = true;
				flush_condition.notify_all();
			});

			if constexpr (!perform_automatically) {
				perform();
			}

			flush_condition.wait(lock, [&has_run] { return has_run; });
		}

		~TaskQueue() {
			stop();
		}

	private:
		// The list of actions waiting be performed. These will be elided,
		// increasing their latency, if the emulation thread falls behind.
		using ActionVector = std::vector<std::function<void(void)>>;
		ActionVector actions_;

		// Necessary synchronisation parts.
		std::atomic<bool> should_quit_ = false;
		std::mutex condition_mutex_;
		std::condition_variable condition_;

		// Ensure the thread isn't constructed until after the mutex
		// and condition variable.
		std::thread thread_;
};

}

#endif /* AsyncTaskQueue_hpp */
<|endoftext|>


<commit_before>#include "KeyframeSelector.hpp"
#include <openMVG/image/image.hpp>
#include <openMVG/features/sift/SIFT_describer.hpp>
#include <openMVG/exif/sensor_width_database/ParseDatabase.hpp>
#include <openMVG/logger.hpp>

#include <tuple>
#include <cassert>

namespace openMVG {
namespace keyframe {

KeyframeSelector::KeyframeSelector(const std::vector<std::string>& mediaPaths,
                                   const std::string& sensorDbPath,
                                   const std::string& voctreeFilePath,
                                   const std::string& outputDirectory)
  : _mediaPaths(mediaPaths)
  , _sensorDbPath(sensorDbPath)
  , _voctreeFilePath(voctreeFilePath)
  , _outputDirectory(outputDirectory)
{
  // load vocabulary tree
  _voctree.reset(new openMVG::voctree::VocabularyTree<DescriptorFloat>(voctreeFilePath));

  {
      OPENMVG_COUT("vocabulary tree loaded with :");
      OPENMVG_COUT(" - " << _voctree->levels() << " levels");
      OPENMVG_COUT(" - " << _voctree->splits() << " branching factor");
  }

  // check number of input media filePaths
  if(mediaPaths.empty())
  {
    OPENMVG_CERR("ERROR : can't create KeyframeSelector without a media file path !");
    throw std::invalid_argument("ERROR : can't create KeyframeSelector without a media file path !");
  }

  // resize mediasInfo container
  _mediasInfo.resize(mediaPaths.size());

  // create feeds and count minimum number of frames
  std::size_t nbFrames = std::numeric_limits<std::size_t>::max();
  for(const auto& path : _mediaPaths)
  {
    // create a feed provider per mediaPaths
    _feeds.emplace_back(new dataio::FeedProvider(path));

    const auto& feed = *_feeds.back();

    // check if feed is initialized
    if(!feed.isInit())
    {
      OPENMVG_CERR("ERROR : while initializing the FeedProvider with " << path);
      throw std::invalid_argument("ERROR : while initializing the FeedProvider with " + path);
    }

    // update minimum number of frames
    nbFrames = std::min(nbFrames, feed.nbFrames());
  }

  // check if minimum number of frame is zero
  if(nbFrames == 0)
  {
    OPENMVG_CERR("ERROR : one or multiple medias are empty (no frames) !");
    throw std::invalid_argument("ERROR : one or multiple medias are empty (no frames) !");
  }

  // resize selection data vector
  _framesData.resize(nbFrames);

  // create SIFT image describer
  _imageDescriber.reset(new features::SIFT_ImageDescriber());
}

void KeyframeSelector::process()
{
  // feed provider variables
  image::Image< image::RGBColor> image;                 // original image
  cameras::Pinhole_Intrinsic_Radial_K3 queryIntrinsics; // image associated camera intrinsics
  bool hasIntrinsics = false;                           // true if queryIntrinsics is valid
  std::string currentImgName;                           // current image name

  // process variables
  const unsigned int frameStep = _maxFrameStep - _minFrameStep;
  const unsigned int tileSharpSubset =  (_nbTileSide * _nbTileSide) / _sharpSubset;

  for(std::size_t mediaIndex = 0 ; mediaIndex < _feeds.size(); ++mediaIndex)
  {
    // first frame
    if(!_feeds.at(mediaIndex)->readImage(image, queryIntrinsics, currentImgName, hasIntrinsics))
    {
      OPENMVG_CERR("ERROR : can't read media first frame " << _mediaPaths[mediaIndex]);
      throw std::invalid_argument("ERROR : can't read media first frame " + _mediaPaths[mediaIndex]);
    }

    // define output image metadata
    if(!_cameraInfos.at(mediaIndex).focalIsMM)
    {
      convertFocalLengthInMM(_cameraInfos.at(mediaIndex), image.Width());
    }

    // define media informations variables
    auto& mediaInfo =  _mediasInfo.at(mediaIndex);
    mediaInfo.tileHeight = (image.Height() / 2) / _nbTileSide;
    mediaInfo.tileWidth = (image.Width() / 2) / _nbTileSide;
    mediaInfo.spec = oiio::ImageSpec(image.Width(), image.Height(), 3, oiio::TypeDesc::UINT8); // always jpeg
    mediaInfo.spec.attribute("CompressionQuality", 100);   // always best compression quality
    mediaInfo.spec.attribute("jpeg:subsampling", "4:4:4"); // always subsampling 4:4:4
    mediaInfo.spec.attribute("oiio:ColorSpace", "sRGB");   // always sRGB
    mediaInfo.spec.attribute("Make",  _cameraInfos[mediaIndex].brand);
    mediaInfo.spec.attribute("Model", _cameraInfos[mediaIndex].model);
    mediaInfo.spec.attribute("Exif:FocalLength", _cameraInfos[mediaIndex].focalLength);
  }

  // iteration process
  _keyframeIndexes.clear();
  std::size_t currentFrameStep = _minFrameStep; // start directly (dont skip minFrameStep first frames)

  for(std::size_t frameIndex = 0; frameIndex < _framesData.size(); ++frameIndex)
  {
    OPENMVG_COUT("frame : " << frameIndex);
    bool frameSelected = true;
    auto& frameData = _framesData.at(frameIndex);
    frameData.mediasData.resize(_feeds.size());

    for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
    {
      OPENMVG_COUT("media : " << _mediaPaths.at(mediaIndex));
      auto& feed = *_feeds.at(mediaIndex);

      if(frameSelected) // false if a camera of a rig is not selected
      {
        if(!feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics))
        {
          OPENMVG_CERR("ERROR  : can't read frame '" << currentImgName << "' !");
          throw std::invalid_argument("ERROR : can't read frame '" + currentImgName + "' !");
        }

        // compute sharpness and sparse distance
        if(!computeFrameData(image, frameIndex, mediaIndex, tileSharpSubset))
        {
          frameSelected = false;
        }
      }

      feed.goToNextFrame();
    }

    {
      if(frameSelected)
      {
        OPENMVG_COUT(" > selected");
        frameData.selected = true;
        frameData.computeAvgSharpness();
      }
      else
      {
        OPENMVG_COUT(" > skipped");
        frameData.mediasData.clear(); // remove unselected mediasData
      }
    }

    // selection process
    if(currentFrameStep >= _maxFrameStep)
    {
      currentFrameStep = _minFrameStep;
      bool hasKeyframe = false;
      std::size_t keyframeIndex = 0;
      float maxSharpness = 0;

      // find the sharpest selected frame
      for(std::size_t index = frameIndex - (frameStep - 1); index <= frameIndex; ++index)
      {
        if(_framesData[index].selected && (_framesData[index].avgSharpness > maxSharpness))
        {
          hasKeyframe = true;
          keyframeIndex = index;
          maxSharpness = _framesData[index].avgSharpness;
        }
      }

      // save keyframe
      if(hasKeyframe)
      {
        OPENMVG_COUT("--> keyframe choice : " << keyframeIndex);
        if(_maxOutFrame == 0) // no limit of keyframes (direct evaluation)
        {
          // write keyframe
          for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
          {
            auto& feed = *_feeds.at(mediaIndex);

            feed.goToFrame(keyframeIndex);
            feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics);

            writeKeyframe(image, keyframeIndex, mediaIndex);
          }
        }
        _framesData[keyframeIndex].keyframe = true;
        _keyframeIndexes.push_back(keyframeIndex);

        frameIndex = keyframeIndex + _minFrameStep - 1;
      }
      else
      {
        OPENMVG_COUT("--> keyframe choice : none");
      }
    }
    ++currentFrameStep;
  }

  if(_maxOutFrame == 0) // no limit of keyframes (evaluation and write already done)
  {
    return;
  }

  // if limited number of keyframe select smallest sparse distance
  {
    std::vector< std::tuple<float, float, std::size_t> > keyframes;

    for(std::size_t i = 0; i < _framesData.size(); ++i)
    {
      if(_framesData[i].keyframe)
      {
        keyframes.emplace_back(_framesData[i].maxDistScore, 1 / _framesData[i].avgSharpness, i);
      }
    }
    std::sort(keyframes.begin(), keyframes.end());

    for(std::size_t i = 0; i < _maxOutFrame; ++i)
    {
      const std::size_t frameIndex = std::get<2>(keyframes.at(i));
      for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
      {
        auto& feed = *_feeds.at(mediaIndex);
        feed.goToFrame(frameIndex);
        feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics);
        writeKeyframe(image, frameIndex, mediaIndex);
      }
    }
  }
}

float KeyframeSelector::computeSharpness(const image::Image<unsigned char>& imageGray,
                                         const unsigned int tileHeight,
                                         const unsigned int tileWidth,
                                         const unsigned int tileSharpSubset) const
{
  image::Image<float> image;
  image::Image<float> scharrXDer;
  image::Image<float> scharrYDer;

  image::ConvertPixelType(imageGray, &image);
  image::ImageScharrXDerivative(image, scharrXDer); // normalized
  image::ImageScharrYDerivative(image, scharrYDer); // normalized

  scharrXDer = scharrXDer.cwiseAbs(); // absolute value
  scharrYDer = scharrYDer.cwiseAbs(); // absolute value

  // image tiles
  std::vector<float> averageTileIntensity;
  const float tileSizeInv = 1 / static_cast<float>(tileHeight * tileWidth);

  for(std::size_t y =  0; y < (_nbTileSide * tileHeight); y += tileHeight)
  {
    for(std::size_t x =  0; x < (_nbTileSide * tileWidth); x += tileWidth)
    {
      const auto sum = scharrXDer.block(y, x, tileHeight, tileWidth).sum() + scharrYDer.block(y, x, tileHeight, tileWidth).sum();
      averageTileIntensity.push_back(sum * tileSizeInv);
    }
  }

  // sort tiles average pixel intensity
  std::sort(averageTileIntensity.begin(), averageTileIntensity.end());

  // return the sum of the subset average pixel intensity
  return std::accumulate(averageTileIntensity.end() - tileSharpSubset, averageTileIntensity.end(), 0.0f) / tileSharpSubset;
}

bool KeyframeSelector::computeFrameData(const image::Image<image::RGBColor>& image,
                                        std::size_t frameIndex,
                                        std::size_t mediaIndex,
                                        unsigned int tileSharpSubset)
{
  image::Image<unsigned char> imageGray;                // grayscale image
  image::Image<unsigned char> imageGrayHalfSample;      // half resolution grayscale image

  const auto& currMediaInfo = _mediasInfo.at(mediaIndex);
  auto& currframeData = _framesData.at(frameIndex);
  auto& currMediaData = currframeData.mediasData.at(mediaIndex);

  // get grayscale image and resize
  image::ConvertPixelType(image, &imageGray);
  image::ImageHalfSample(imageGray, imageGrayHalfSample);

  // compute sharpness
  currMediaData.sharpness = computeSharpness(imageGrayHalfSample,
                                             currMediaInfo.tileHeight,
                                             currMediaInfo.tileWidth,
                                             tileSharpSubset);

  OPENMVG_COUT( " - sharpness : " << currMediaData.sharpness);

  if(currMediaData.sharpness > _sharpnessThreshold)
  {
    bool noKeyframe = (_keyframeIndexes.empty());

    // compute current frame sparse histogram
    std::unique_ptr<features::Regions> regions;
    _imageDescriber->Describe(imageGrayHalfSample, regions);
    currMediaData.histogram = voctree::SparseHistogram(_voctree->quantizeToSparse(dynamic_cast<features::SIFT_Regions*>(regions.get())->Descriptors()));

    // compute sparseDistance
    if(!noKeyframe)
    {
      unsigned int nbKeyframetoCompare = (_keyframeIndexes.size() < _nbKeyFrameDist)? _keyframeIndexes.size() : _nbKeyFrameDist;

      for(std::size_t i = _keyframeIndexes.size() - nbKeyframetoCompare; i < _keyframeIndexes.size(); ++i)
      {
        for(auto& media : _framesData.at(_keyframeIndexes.at(i)).mediasData)
        {
          currMediaData.distScore = std::max(currMediaData.distScore, std::abs(voctree::sparseDistance(media.histogram, currMediaData.histogram, "strongCommonPoints")));
        }
      }
      currframeData.maxDistScore = std::max(currframeData.maxDistScore, currMediaData.distScore);
      OPENMVG_COUT(" - distScore : " << currMediaData.distScore);
    }

    if(noKeyframe || (currMediaData.distScore < _distScoreMax))
    {
      return true;
    }
  }
  return false;
}

void KeyframeSelector::writeKeyframe(const image::Image<image::RGBColor>& image,
                                     std::size_t frameIndex,
                                     std::size_t mediaIndex)
{
  const auto& mediaInfo = _mediasInfo.at(mediaIndex);
  const auto filepath = _outputDirectory + "/frame_" + to_string(frameIndex) + "_media_" + to_string(mediaIndex) + ".jpg";

  std::unique_ptr<oiio::ImageOutput> out(oiio::ImageOutput::create(filepath));

  if(out.get() == nullptr)
  {
    throw std::invalid_argument("ERROR : can't create image file : " + filepath);
  }

  if(!out->open(filepath, mediaInfo.spec))
  {
    throw std::invalid_argument("ERROR : can't open image file : " + filepath);
  }

  out->write_image(oiio::TypeDesc::UINT8, image.data()); // always jpeg
  out->close();
}

void KeyframeSelector::convertFocalLengthInMM(CameraInfo& cameraInfo, int imageWidth)
{
  assert(imageWidth > 0);

  exif::sensordb::Datasheet find;
  std::vector<exif::sensordb::Datasheet> vecDatabase;
  exif::sensordb::parseDatabase(_sensorDbPath, vecDatabase);

  if(exif::sensordb::getInfo(cameraInfo.brand, cameraInfo.model, vecDatabase, find))
  {
    cameraInfo.focalLength = (cameraInfo.focalLength * find._sensorSize) / imageWidth;
    cameraInfo.focalIsMM = true;
    OPENMVG_COUT("INFO : Focal length converted in mm : " << cameraInfo.focalLength);
  }
  else
  {
    OPENMVG_COUT("WARNING : can't convert focal length in mm  : " << cameraInfo.brand << " / " << cameraInfo.model);
  }
}

} // namespace keyframe
} // namespace openMVG
<commit_msg>[keyframe] add log level<commit_after>#include "KeyframeSelector.hpp"
#include <openMVG/image/image.hpp>
#include <openMVG/features/sift/SIFT_describer.hpp>
#include <openMVG/exif/sensor_width_database/ParseDatabase.hpp>
#include <openMVG/logger.hpp>

#include <tuple>
#include <cassert>

namespace openMVG {
namespace keyframe {

KeyframeSelector::KeyframeSelector(const std::vector<std::string>& mediaPaths,
                                   const std::string& sensorDbPath,
                                   const std::string& voctreeFilePath,
                                   const std::string& outputDirectory)
  : _mediaPaths(mediaPaths)
  , _sensorDbPath(sensorDbPath)
  , _voctreeFilePath(voctreeFilePath)
  , _outputDirectory(outputDirectory)
{
  // load vocabulary tree
  _voctree.reset(new openMVG::voctree::VocabularyTree<DescriptorFloat>(voctreeFilePath));

  {
      OPENMVG_LOG_INFO("vocabulary tree loaded with :" << std::endl
                       << " - " << _voctree->levels() << " levels" << std::endl
                       << " - " << _voctree->splits() << " branching factor" << std::endl);
  }

  // check number of input media filePaths
  if(mediaPaths.empty())
  {
    OPENMVG_LOG_ERROR("ERROR : can't create KeyframeSelector without a media file path !");
    throw std::invalid_argument("ERROR : can't create KeyframeSelector without a media file path !");
  }

  // resize mediasInfo container
  _mediasInfo.resize(mediaPaths.size());

  // create feeds and count minimum number of frames
  std::size_t nbFrames = std::numeric_limits<std::size_t>::max();
  for(const auto& path : _mediaPaths)
  {
    // create a feed provider per mediaPaths
    _feeds.emplace_back(new dataio::FeedProvider(path));

    const auto& feed = *_feeds.back();

    // check if feed is initialized
    if(!feed.isInit())
    {
      OPENMVG_LOG_ERROR("ERROR : while initializing the FeedProvider with " << path);
      throw std::invalid_argument("ERROR : while initializing the FeedProvider with " + path);
    }

    // update minimum number of frames
    nbFrames = std::min(nbFrames, feed.nbFrames());
  }

  // check if minimum number of frame is zero
  if(nbFrames == 0)
  {
    OPENMVG_LOG_ERROR("ERROR : one or multiple medias are empty (no frames) !");
    throw std::invalid_argument("ERROR : one or multiple medias are empty (no frames) !");
  }

  // resize selection data vector
  _framesData.resize(nbFrames);

  // create SIFT image describer
  _imageDescriber.reset(new features::SIFT_ImageDescriber());
}

void KeyframeSelector::process()
{
  // feed provider variables
  image::Image< image::RGBColor> image;                 // original image
  cameras::Pinhole_Intrinsic_Radial_K3 queryIntrinsics; // image associated camera intrinsics
  bool hasIntrinsics = false;                           // true if queryIntrinsics is valid
  std::string currentImgName;                           // current image name

  // process variables
  const unsigned int frameStep = _maxFrameStep - _minFrameStep;
  const unsigned int tileSharpSubset =  (_nbTileSide * _nbTileSide) / _sharpSubset;

  for(std::size_t mediaIndex = 0 ; mediaIndex < _feeds.size(); ++mediaIndex)
  {
    // first frame
    if(!_feeds.at(mediaIndex)->readImage(image, queryIntrinsics, currentImgName, hasIntrinsics))
    {
      OPENMVG_LOG_ERROR("ERROR : can't read media first frame " << _mediaPaths[mediaIndex]);
      throw std::invalid_argument("ERROR : can't read media first frame " + _mediaPaths[mediaIndex]);
    }

    // define output image metadata
    if(!_cameraInfos.at(mediaIndex).focalIsMM)
    {
      convertFocalLengthInMM(_cameraInfos.at(mediaIndex), image.Width());
    }

    // define media informations variables
    auto& mediaInfo =  _mediasInfo.at(mediaIndex);
    mediaInfo.tileHeight = (image.Height() / 2) / _nbTileSide;
    mediaInfo.tileWidth = (image.Width() / 2) / _nbTileSide;
    mediaInfo.spec = oiio::ImageSpec(image.Width(), image.Height(), 3, oiio::TypeDesc::UINT8); // always jpeg
    mediaInfo.spec.attribute("CompressionQuality", 100);   // always best compression quality
    mediaInfo.spec.attribute("jpeg:subsampling", "4:4:4"); // always subsampling 4:4:4
    mediaInfo.spec.attribute("oiio:ColorSpace", "sRGB");   // always sRGB
    mediaInfo.spec.attribute("Make",  _cameraInfos[mediaIndex].brand);
    mediaInfo.spec.attribute("Model", _cameraInfos[mediaIndex].model);
    mediaInfo.spec.attribute("Exif:FocalLength", _cameraInfos[mediaIndex].focalLength);
  }

  // iteration process
  _keyframeIndexes.clear();
  std::size_t currentFrameStep = _minFrameStep; // start directly (dont skip minFrameStep first frames)

  for(std::size_t frameIndex = 0; frameIndex < _framesData.size(); ++frameIndex)
  {
    OPENMVG_LOG_TRACE("frame : " << frameIndex);
    bool frameSelected = true;
    auto& frameData = _framesData.at(frameIndex);
    frameData.mediasData.resize(_feeds.size());

    for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
    {
      OPENMVG_LOG_TRACE("media : " << _mediaPaths.at(mediaIndex));
      auto& feed = *_feeds.at(mediaIndex);

      if(frameSelected) // false if a camera of a rig is not selected
      {
        if(!feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics))
        {
          OPENMVG_LOG_ERROR("ERROR  : can't read frame '" << currentImgName << "' !");
          throw std::invalid_argument("ERROR : can't read frame '" + currentImgName + "' !");
        }

        // compute sharpness and sparse distance
        if(!computeFrameData(image, frameIndex, mediaIndex, tileSharpSubset))
        {
          frameSelected = false;
        }
      }

      feed.goToNextFrame();
    }

    {
      if(frameSelected)
      {
        OPENMVG_LOG_TRACE(" > selected");
        frameData.selected = true;
        frameData.computeAvgSharpness();
      }
      else
      {
        OPENMVG_LOG_TRACE(" > skipped");
        frameData.mediasData.clear(); // remove unselected mediasData
      }
    }

    // selection process
    if(currentFrameStep >= _maxFrameStep)
    {
      currentFrameStep = _minFrameStep;
      bool hasKeyframe = false;
      std::size_t keyframeIndex = 0;
      float maxSharpness = 0;

      // find the sharpest selected frame
      for(std::size_t index = frameIndex - (frameStep - 1); index <= frameIndex; ++index)
      {
        if(_framesData[index].selected && (_framesData[index].avgSharpness > maxSharpness))
        {
          hasKeyframe = true;
          keyframeIndex = index;
          maxSharpness = _framesData[index].avgSharpness;
        }
      }

      // save keyframe
      if(hasKeyframe)
      {
        OPENMVG_LOG_INFO("keyframe choice : " << keyframeIndex);
        if(_maxOutFrame == 0) // no limit of keyframes (direct evaluation)
        {
          // write keyframe
          for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
          {
            auto& feed = *_feeds.at(mediaIndex);

            feed.goToFrame(keyframeIndex);
            feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics);

            writeKeyframe(image, keyframeIndex, mediaIndex);
          }
        }
        _framesData[keyframeIndex].keyframe = true;
        _keyframeIndexes.push_back(keyframeIndex);

        frameIndex = keyframeIndex + _minFrameStep - 1;
      }
      else
      {
        OPENMVG_LOG_INFO("keyframe choice : none");
      }
    }
    ++currentFrameStep;
  }

  if(_maxOutFrame == 0) // no limit of keyframes (evaluation and write already done)
  {
    return;
  }

  // if limited number of keyframe select smallest sparse distance
  {
    std::vector< std::tuple<float, float, std::size_t> > keyframes;

    for(std::size_t i = 0; i < _framesData.size(); ++i)
    {
      if(_framesData[i].keyframe)
      {
        keyframes.emplace_back(_framesData[i].maxDistScore, 1 / _framesData[i].avgSharpness, i);
      }
    }
    std::sort(keyframes.begin(), keyframes.end());

    for(std::size_t i = 0; i < _maxOutFrame; ++i)
    {
      const std::size_t frameIndex = std::get<2>(keyframes.at(i));
      for(std::size_t mediaIndex = 0; mediaIndex < _feeds.size(); ++mediaIndex)
      {
        auto& feed = *_feeds.at(mediaIndex);
        feed.goToFrame(frameIndex);
        feed.readImage(image, queryIntrinsics, currentImgName, hasIntrinsics);
        writeKeyframe(image, frameIndex, mediaIndex);
      }
    }
  }
}

float KeyframeSelector::computeSharpness(const image::Image<unsigned char>& imageGray,
                                         const unsigned int tileHeight,
                                         const unsigned int tileWidth,
                                         const unsigned int tileSharpSubset) const
{
  image::Image<float> image;
  image::Image<float> scharrXDer;
  image::Image<float> scharrYDer;

  image::ConvertPixelType(imageGray, &image);
  image::ImageScharrXDerivative(image, scharrXDer); // normalized
  image::ImageScharrYDerivative(image, scharrYDer); // normalized

  scharrXDer = scharrXDer.cwiseAbs(); // absolute value
  scharrYDer = scharrYDer.cwiseAbs(); // absolute value

  // image tiles
  std::vector<float> averageTileIntensity;
  const float tileSizeInv = 1 / static_cast<float>(tileHeight * tileWidth);

  for(std::size_t y =  0; y < (_nbTileSide * tileHeight); y += tileHeight)
  {
    for(std::size_t x =  0; x < (_nbTileSide * tileWidth); x += tileWidth)
    {
      const auto sum = scharrXDer.block(y, x, tileHeight, tileWidth).sum() + scharrYDer.block(y, x, tileHeight, tileWidth).sum();
      averageTileIntensity.push_back(sum * tileSizeInv);
    }
  }

  // sort tiles average pixel intensity
  std::sort(averageTileIntensity.begin(), averageTileIntensity.end());

  // return the sum of the subset average pixel intensity
  return std::accumulate(averageTileIntensity.end() - tileSharpSubset, averageTileIntensity.end(), 0.0f) / tileSharpSubset;
}

bool KeyframeSelector::computeFrameData(const image::Image<image::RGBColor>& image,
                                        std::size_t frameIndex,
                                        std::size_t mediaIndex,
                                        unsigned int tileSharpSubset)
{
  image::Image<unsigned char> imageGray;                // grayscale image
  image::Image<unsigned char> imageGrayHalfSample;      // half resolution grayscale image

  const auto& currMediaInfo = _mediasInfo.at(mediaIndex);
  auto& currframeData = _framesData.at(frameIndex);
  auto& currMediaData = currframeData.mediasData.at(mediaIndex);

  // get grayscale image and resize
  image::ConvertPixelType(image, &imageGray);
  image::ImageHalfSample(imageGray, imageGrayHalfSample);

  // compute sharpness
  currMediaData.sharpness = computeSharpness(imageGrayHalfSample,
                                             currMediaInfo.tileHeight,
                                             currMediaInfo.tileWidth,
                                             tileSharpSubset);

  OPENMVG_LOG_TRACE( " - sharpness : " << currMediaData.sharpness);

  if(currMediaData.sharpness > _sharpnessThreshold)
  {
    bool noKeyframe = (_keyframeIndexes.empty());

    // compute current frame sparse histogram
    std::unique_ptr<features::Regions> regions;
    _imageDescriber->Describe(imageGrayHalfSample, regions);
    currMediaData.histogram = voctree::SparseHistogram(_voctree->quantizeToSparse(dynamic_cast<features::SIFT_Regions*>(regions.get())->Descriptors()));

    // compute sparseDistance
    if(!noKeyframe)
    {
      unsigned int nbKeyframetoCompare = (_keyframeIndexes.size() < _nbKeyFrameDist)? _keyframeIndexes.size() : _nbKeyFrameDist;

      for(std::size_t i = _keyframeIndexes.size() - nbKeyframetoCompare; i < _keyframeIndexes.size(); ++i)
      {
        for(auto& media : _framesData.at(_keyframeIndexes.at(i)).mediasData)
        {
          currMediaData.distScore = std::max(currMediaData.distScore, std::abs(voctree::sparseDistance(media.histogram, currMediaData.histogram, "strongCommonPoints")));
        }
      }
      currframeData.maxDistScore = std::max(currframeData.maxDistScore, currMediaData.distScore);
      OPENMVG_LOG_TRACE(" - distScore : " << currMediaData.distScore);
    }

    if(noKeyframe || (currMediaData.distScore < _distScoreMax))
    {
      return true;
    }
  }
  return false;
}

void KeyframeSelector::writeKeyframe(const image::Image<image::RGBColor>& image,
                                     std::size_t frameIndex,
                                     std::size_t mediaIndex)
{
  const auto& mediaInfo = _mediasInfo.at(mediaIndex);
  const auto filepath = _outputDirectory + "/frame_" + to_string(frameIndex) + "_media_" + to_string(mediaIndex) + ".jpg";

  std::unique_ptr<oiio::ImageOutput> out(oiio::ImageOutput::create(filepath));

  if(out.get() == nullptr)
  {
    throw std::invalid_argument("ERROR : can't create image file : " + filepath);
  }

  if(!out->open(filepath, mediaInfo.spec))
  {
    throw std::invalid_argument("ERROR : can't open image file : " + filepath);
  }

  out->write_image(oiio::TypeDesc::UINT8, image.data()); // always jpeg
  out->close();
}

void KeyframeSelector::convertFocalLengthInMM(CameraInfo& cameraInfo, int imageWidth)
{
  assert(imageWidth > 0);

  exif::sensordb::Datasheet find;
  std::vector<exif::sensordb::Datasheet> vecDatabase;
  exif::sensordb::parseDatabase(_sensorDbPath, vecDatabase);

  if(exif::sensordb::getInfo(cameraInfo.brand, cameraInfo.model, vecDatabase, find))
  {
    cameraInfo.focalLength = (cameraInfo.focalLength * find._sensorSize) / imageWidth;
    cameraInfo.focalIsMM = true;
    OPENMVG_LOG_INFO("Focal length converted in mm : " << cameraInfo.focalLength);
  }
  else
  {
    OPENMVG_LOG_WARNING("Warning: can't convert focal length in mm  : " << cameraInfo.brand << " / " << cameraInfo.model);
  }
}

} // namespace keyframe
} // namespace openMVG
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "buildconfiguration.h"

#include "buildmanager.h"
#include "buildsteplist.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "target.h"

#include <QtCore/QProcess>

using namespace ProjectExplorer;

namespace {

const char * const BUILD_STEP_LIST_COUNT("ProjectExplorer.BuildConfiguration.BuildStepListCount");
const char * const BUILD_STEP_LIST_PREFIX("ProjectExplorer.BuildConfiguration.BuildStepList.");
const char * const CLEAR_SYSTEM_ENVIRONMENT_KEY("ProjectExplorer.BuildConfiguration.ClearSystemEnvironment");
const char * const USER_ENVIRONMENT_CHANGES_KEY("ProjectExplorer.BuildConfiguration.UserEnvironmentChanges");

} // namespace

BuildConfiguration::BuildConfiguration(Target *target, const QString &id) :
    ProjectConfiguration(target, id),
    m_clearSystemEnvironment(false)
{
    Q_ASSERT(target);
    BuildStepList *bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_BUILD));
    //: Display name of the build build step list. Used as part of the labels in the project window.
    bsl->setDisplayName(tr("Build"));
    m_stepLists.append(bsl);
    bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_CLEAN));
    //: Display name of the clean build step list. Used as part of the labels in the project window.
    bsl->setDisplayName(tr("Clean"));
    m_stepLists.append(bsl);
}

BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *source) :
    ProjectConfiguration(target, source),
    m_clearSystemEnvironment(source->m_clearSystemEnvironment),
    m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
    Q_ASSERT(target);
    // Do not clone stepLists here, do that in the derived constructor instead
    // otherwise BuildStepFactories might reject to set up a BuildStep for us
    // since we are not yet the derived class!
}

BuildConfiguration::~BuildConfiguration()
{ }

QStringList BuildConfiguration::knownStepLists() const
{
    QStringList result;
    foreach (BuildStepList *list, m_stepLists)
        result.append(list->id());
    return result;
}

BuildStepList *BuildConfiguration::stepList(const QString &id) const
{
    foreach (BuildStepList *list, m_stepLists)
        if (id == list->id())
            return list;
    return 0;
}

QVariantMap BuildConfiguration::toMap() const
{
    QVariantMap map(ProjectConfiguration::toMap());
    map.insert(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY), m_clearSystemEnvironment);
    map.insert(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY), EnvironmentItem::toStringList(m_userEnvironmentChanges));

    map.insert(QLatin1String(BUILD_STEP_LIST_COUNT), m_stepLists.count());
    for (int i = 0; i < m_stepLists.count(); ++i)
        map.insert(QLatin1String(BUILD_STEP_LIST_PREFIX) % QString::number(i), m_stepLists.at(i)->toMap());

    return map;
}

bool BuildConfiguration::fromMap(const QVariantMap &map)
{
    if (!ProjectConfiguration::fromMap(map))
        return false;

    m_clearSystemEnvironment = map.value(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY)).toBool();
    m_userEnvironmentChanges = EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList());

    qDeleteAll(m_stepLists);
    m_stepLists.clear();

    int maxI = map.value(QLatin1String(BUILD_STEP_LIST_COUNT), 0).toInt();
    for (int i = 0; i < maxI; ++i) {
        QVariantMap data = map.value(QLatin1String(BUILD_STEP_LIST_PREFIX) % QString::number(i)).toMap();
        if (data.isEmpty()) {
            qWarning() << "No data for build step list" << i << "found!";
            continue;
        }
        BuildStepList *list = new BuildStepList(this, data);
        if (list->isNull()) {
            qWarning() << "Failed to restore build step list" << i;
            delete list;
            return false;
        }
        m_stepLists.append(list);
    }

    // TODO: We currently assume there to be at least a clean, build and deploy list!
    Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD)));
    Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)));

    return true;
}

Target *BuildConfiguration::target() const
{
    return static_cast<Target *>(parent());
}

Environment BuildConfiguration::baseEnvironment() const
{
    if (useSystemEnvironment())
        return Environment(QProcess::systemEnvironment());
    return Environment();
}

QString BuildConfiguration::baseEnvironmentText() const
{
    if (useSystemEnvironment())
        return tr("System Environment");
    else
        return tr("Clean Environment");
}

Environment BuildConfiguration::environment() const
{
    Environment env = baseEnvironment();
    env.modify(userEnvironmentChanges());
    return env;
}

void BuildConfiguration::setUseSystemEnvironment(bool b)
{
    if (useSystemEnvironment() == b)
        return;
    m_clearSystemEnvironment = !b;
    emit environmentChanged();
}

bool BuildConfiguration::useSystemEnvironment() const
{
    return !m_clearSystemEnvironment;
}

QList<EnvironmentItem> BuildConfiguration::userEnvironmentChanges() const
{
    return m_userEnvironmentChanges;
}

void BuildConfiguration::setUserEnvironmentChanges(const QList<ProjectExplorer::EnvironmentItem> &diff)
{
    if (m_userEnvironmentChanges == diff)
        return;
    m_userEnvironmentChanges = diff;
    emit environmentChanged();
}

void BuildConfiguration::cloneSteps(BuildConfiguration *source)
{
    qDeleteAll(m_stepLists);
    m_stepLists.clear();
    foreach (BuildStepList *bsl, source->m_stepLists) {
        BuildStepList *newBsl = new BuildStepList(this, bsl);
        m_stepLists.append(newBsl);
    }
}

///
// IBuildConfigurationFactory
///

IBuildConfigurationFactory::IBuildConfigurationFactory(QObject *parent) :
    QObject(parent)
{ }

IBuildConfigurationFactory::~IBuildConfigurationFactory()
{ }
<commit_msg>Build fix for mac<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "buildconfiguration.h"

#include "buildmanager.h"
#include "buildsteplist.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "target.h"

#include <QtCore/QProcess>

using namespace ProjectExplorer;

namespace {

const char * const BUILD_STEP_LIST_COUNT("ProjectExplorer.BuildConfiguration.BuildStepListCount");
const char * const BUILD_STEP_LIST_PREFIX("ProjectExplorer.BuildConfiguration.BuildStepList.");
const char * const CLEAR_SYSTEM_ENVIRONMENT_KEY("ProjectExplorer.BuildConfiguration.ClearSystemEnvironment");
const char * const USER_ENVIRONMENT_CHANGES_KEY("ProjectExplorer.BuildConfiguration.UserEnvironmentChanges");

} // namespace

BuildConfiguration::BuildConfiguration(Target *target, const QString &id) :
    ProjectConfiguration(target, id),
    m_clearSystemEnvironment(false)
{
    Q_ASSERT(target);
    BuildStepList *bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_BUILD));
    //: Display name of the build build step list. Used as part of the labels in the project window.
    bsl->setDisplayName(tr("Build"));
    m_stepLists.append(bsl);
    bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_CLEAN));
    //: Display name of the clean build step list. Used as part of the labels in the project window.
    bsl->setDisplayName(tr("Clean"));
    m_stepLists.append(bsl);
}

BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *source) :
    ProjectConfiguration(target, source),
    m_clearSystemEnvironment(source->m_clearSystemEnvironment),
    m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
    Q_ASSERT(target);
    // Do not clone stepLists here, do that in the derived constructor instead
    // otherwise BuildStepFactories might reject to set up a BuildStep for us
    // since we are not yet the derived class!
}

BuildConfiguration::~BuildConfiguration()
{ }

QStringList BuildConfiguration::knownStepLists() const
{
    QStringList result;
    foreach (BuildStepList *list, m_stepLists)
        result.append(list->id());
    return result;
}

BuildStepList *BuildConfiguration::stepList(const QString &id) const
{
    foreach (BuildStepList *list, m_stepLists)
        if (id == list->id())
            return list;
    return 0;
}

QVariantMap BuildConfiguration::toMap() const
{
    QVariantMap map(ProjectConfiguration::toMap());
    map.insert(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY), m_clearSystemEnvironment);
    map.insert(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY), EnvironmentItem::toStringList(m_userEnvironmentChanges));

    map.insert(QLatin1String(BUILD_STEP_LIST_COUNT), m_stepLists.count());
    for (int i = 0; i < m_stepLists.count(); ++i)
        map.insert(QLatin1String(BUILD_STEP_LIST_PREFIX) + QString::number(i), m_stepLists.at(i)->toMap());

    return map;
}

bool BuildConfiguration::fromMap(const QVariantMap &map)
{
    if (!ProjectConfiguration::fromMap(map))
        return false;

    m_clearSystemEnvironment = map.value(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY)).toBool();
    m_userEnvironmentChanges = EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList());

    qDeleteAll(m_stepLists);
    m_stepLists.clear();

    int maxI = map.value(QLatin1String(BUILD_STEP_LIST_COUNT), 0).toInt();
    for (int i = 0; i < maxI; ++i) {
        QVariantMap data = map.value(QLatin1String(BUILD_STEP_LIST_PREFIX) + QString::number(i)).toMap();
        if (data.isEmpty()) {
            qWarning() << "No data for build step list" << i << "found!";
            continue;
        }
        BuildStepList *list = new BuildStepList(this, data);
        if (list->isNull()) {
            qWarning() << "Failed to restore build step list" << i;
            delete list;
            return false;
        }
        m_stepLists.append(list);
    }

    // TODO: We currently assume there to be at least a clean, build and deploy list!
    Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD)));
    Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)));

    return true;
}

Target *BuildConfiguration::target() const
{
    return static_cast<Target *>(parent());
}

Environment BuildConfiguration::baseEnvironment() const
{
    if (useSystemEnvironment())
        return Environment(QProcess::systemEnvironment());
    return Environment();
}

QString BuildConfiguration::baseEnvironmentText() const
{
    if (useSystemEnvironment())
        return tr("System Environment");
    else
        return tr("Clean Environment");
}

Environment BuildConfiguration::environment() const
{
    Environment env = baseEnvironment();
    env.modify(userEnvironmentChanges());
    return env;
}

void BuildConfiguration::setUseSystemEnvironment(bool b)
{
    if (useSystemEnvironment() == b)
        return;
    m_clearSystemEnvironment = !b;
    emit environmentChanged();
}

bool BuildConfiguration::useSystemEnvironment() const
{
    return !m_clearSystemEnvironment;
}

QList<EnvironmentItem> BuildConfiguration::userEnvironmentChanges() const
{
    return m_userEnvironmentChanges;
}

void BuildConfiguration::setUserEnvironmentChanges(const QList<ProjectExplorer::EnvironmentItem> &diff)
{
    if (m_userEnvironmentChanges == diff)
        return;
    m_userEnvironmentChanges = diff;
    emit environmentChanged();
}

void BuildConfiguration::cloneSteps(BuildConfiguration *source)
{
    qDeleteAll(m_stepLists);
    m_stepLists.clear();
    foreach (BuildStepList *bsl, source->m_stepLists) {
        BuildStepList *newBsl = new BuildStepList(this, bsl);
        m_stepLists.append(newBsl);
    }
}

///
// IBuildConfigurationFactory
///

IBuildConfigurationFactory::IBuildConfigurationFactory(QObject *parent) :
    QObject(parent)
{ }

IBuildConfigurationFactory::~IBuildConfigurationFactory()
{ }
<|endoftext|>


<commit_before>#include <stdio.h>
#include <sys/time.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <unistd.h>
#include <common/cycles.h>
#include <common/dump_utils.h>

#include "nvme_device.h"

void basic_block_read(NVME_device * dev, size_t num_blocks) {

  PLOG("running basic_block_read..");
  const unsigned qid = 1;
  assert(num_blocks < 256);

  Notify_object nobj;

  /* set up call back */
  dev->io_queue(qid)->callback_manager()->register_callback(1,
                                                            &Notify_object::notify_callback,
                                                            (void*)&nobj);

  addr_t phys = 0;
  void * p = Exokernel::Memory::alloc_pages(1,&phys);

  assert(p);
  assert(phys);

  uint16_t cid;
  for(unsigned i=0;i<num_blocks;i++) {

    cid = dev->block_async_read(qid,
                                phys,
                                i, /* LBA */
                                1); /* num blocks */

    PLOG("Block read cid=%u",cid);

    hexdump(p,512);
  }
  nobj.set_when(cid);
  nobj.wait();
  PLOG("expected block reads complete.");

  Exokernel::Memory::free_pages(p);
}

void basic_block_write(NVME_device * dev, size_t num_blocks) {

  PLOG("running basic_block_write..");
  //  Exokernel::Memory::huge_system_configure_nrpages(10);
  const unsigned qid = 1;
  Notify_object nobj;

  /* set up call back */
  dev->io_queue(qid)->callback_manager()->register_callback(1,
                                                            &Notify_object::notify_callback,
                                                            (void*)&nobj);

  unsigned num_data_pages = 4;
  unsigned num_data_blocks = (PAGE_SIZE * num_data_pages) / 512;

  PLOG("Allocated %d pages, %d blocks",num_data_pages, num_data_blocks);

  addr_t phys = 0;
  //  void * p = Exokernel::Memory::alloc_pages(num_data_pages,&phys);
  void * p = dev->alloc_dma_pages(num_data_pages,&phys);
  memset(p,0xfe,num_data_pages*PAGE_SIZE);
  assert(p);
  assert(phys);

  char * q = (char *) p;
  for(unsigned i=0;i<num_data_blocks;i++) {
    /* write a value in */
    memset(q,i+1,512);
    q+=512;
  }

  uint16_t cid;
  //  for(unsigned i=0;i<num_blocks;i++) {
  for(unsigned i=0;i<1;i++) {

    cid = dev->block_async_write(qid,
                                 phys+((i+8)*512), //phys+((i%num_data_blocks)*512),
                                 i, /* LBA */
                                 1);/* num blocks */

    PLOG("*** Block written cid=%u",cid);
  }

  nobj.set_when(cid);
  nobj.wait();
  PLOG("******** Blocks written!!!");

  Exokernel::Memory::free_pages(p);
}
<commit_msg>changed to device allocated memory<commit_after>#include <stdio.h>
#include <sys/time.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <unistd.h>
#include <common/cycles.h>
#include <common/dump_utils.h>

#include "nvme_device.h"

void basic_block_read(NVME_device * dev, size_t num_blocks) {

  PLOG("running basic_block_read..");
  const unsigned qid = 1;
  assert(num_blocks < 256);

  Notify_object nobj;

  /* set up call back */
  dev->io_queue(qid)->callback_manager()->register_callback(1,
                                                            &Notify_object::notify_callback,
                                                            (void*)&nobj);

  addr_t phys = 0;
  void * p = dev->alloc_dma_pages(1,&phys);

  assert(p);
  assert(phys);

  uint16_t cid;
  for(unsigned i=0;i<num_blocks;i++) {

    cid = dev->block_async_read(qid,
                                phys,
                                i, /* LBA */
                                1); /* num blocks */

    PLOG("Block read cid=%u",cid);

    hexdump(p,512);
  }
  nobj.set_when(cid);
  nobj.wait();
  PLOG("expected block reads complete.");

  dev->free_dma_pages(p);
}

void basic_block_write(NVME_device * dev, size_t num_blocks) {

  PLOG("running basic_block_write..");
  //  Exokernel::Memory::huge_system_configure_nrpages(10);
  const unsigned qid = 1;
  Notify_object nobj;

  /* set up call back */
  dev->io_queue(qid)->callback_manager()->register_callback(1,
                                                            &Notify_object::notify_callback,
                                                            (void*)&nobj);

  unsigned num_data_pages = 4;
  unsigned num_data_blocks = (PAGE_SIZE * num_data_pages) / 512;

  PLOG("Allocated %d pages, %d blocks",num_data_pages, num_data_blocks);

  addr_t phys = 0;
  //  void * p = Exokernel::Memory::alloc_pages(num_data_pages,&phys);
  void * p = dev->alloc_dma_pages(num_data_pages,&phys);
  memset(p,0xfe,num_data_pages*PAGE_SIZE);
  assert(p);
  assert(phys);

  char * q = (char *) p;
  for(unsigned i=0;i<num_data_blocks;i++) {
    /* write a value in */
    memset(q,i+1,512);
    q+=512;
  }

  uint16_t cid;
  //  for(unsigned i=0;i<num_blocks;i++) {
  for(unsigned i=0;i<1;i++) {

    cid = dev->block_async_write(qid,
                                 phys+((i+8)*512), //phys+((i%num_data_blocks)*512),
                                 i, /* LBA */
                                 1);/* num blocks */

    PLOG("*** Block written cid=%u",cid);
  }

  nobj.set_when(cid);
  nobj.wait();
  PLOG("******** Blocks written!!!");

  dev->free_dma_pages(p);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <boost/config.hpp>

int test_main();

extern bool tests_failure;

int main()
{
#ifdef O_NONBLOCK
	// on darwin, stdout is set to non-blocking mode by default
	// which sometimes causes tests to fail with EAGAIN just
	// by printing logs
	int flags = fcntl(stdout, F_GETFL, 0);
	fcntl(stdout, F_SETFL, flags & ~O_NONBLOCK);
#endif

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		test_main();
		return tests_failure ? 1 : 0;
#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception const& e)
	{
		std::cerr << "Terminated with exception: \"" << e.what() << "\"\n";
		return 1;
	}
	catch (...)
	{
		std::cerr << "Terminated with unknown exception\n";
		return 1;
	}
#endif
}

<commit_msg>stdout non-blocking fix for tests<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <boost/config.hpp>
#include <fcntl.h>

int test_main();

extern bool tests_failure;

int main()
{
#ifdef O_NONBLOCK
	// on darwin, stdout is set to non-blocking mode by default
	// which sometimes causes tests to fail with EAGAIN just
	// by printing logs
	int flags = fcntl(fileno(stdout), F_GETFL, 0);
	fcntl(fileno(stdout), F_SETFL, flags & ~O_NONBLOCK);
	flags = fcntl(fileno(stderr), F_GETFL, 0);
	fcntl(fileno(stderr), F_SETFL, flags & ~O_NONBLOCK);
#endif

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		test_main();
#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception const& e)
	{
		std::cerr << "Terminated with exception: \"" << e.what() << "\"\n";
		tests_failure = true;
	}
	catch (...)
	{
		std::cerr << "Terminated with unknown exception\n";
		tests_failure = true;
	}
#endif
	fflush(stdout);
	fflush(stderr);
	return tests_failure ? 1 : 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: listviewitems.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 17:52:16 $
 *
 *  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 EXPRESS 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 _DBAUI_LISTVIEWITEMS_HXX_
#include "listviewitems.hxx"
#endif

//........................................................................
namespace dbaui
{
//........................................................................

    //========================================================================
    // class OBoldListboxString
    //========================================================================
    //------------------------------------------------------------------------
    void OBoldListboxString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* _pViewData)
    {
        SvLBoxString::InitViewData(pView,pEntry, _pViewData);
        if (!_pViewData)
            _pViewData = pView->GetViewDataItem( pEntry, this );

        Font aOldFont( pView->GetFont());
        Font aFont( aOldFont );
        aFont.SetWeight(WEIGHT_BOLD);
        pView->SetFont( aFont );

        _pViewData->aSize = Size(pView->GetTextWidth(GetText()), pView->GetTextHeight());
        pView->SetFont( aOldFont );
    }

    //------------------------------------------------------------------------
    USHORT OBoldListboxString::IsA()
    {
        return SV_ITEM_ID_BOLDLBSTRING;
    }

    //------------------------------------------------------------------------
    void OBoldListboxString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry )
    {
        if (m_bEmphasized)
        {
            Font aOldFont( rDev.GetFont());
            Font aFont( aOldFont );
            aFont.SetWeight(WEIGHT_BOLD);
            rDev.SetFont( aFont );

            Point aPos(rPos);
            rDev.DrawText( aPos, GetText() );
            rDev.SetFont( aOldFont );
        }
        else
            SvLBoxString::Paint(rPos, rDev, nFlags, pEntry);
    }

//........................................................................
}   // namespace dbaui
//........................................................................

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.434); FILE MERGED 2005/09/05 17:33:24 rt 1.2.434.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: listviewitems.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:34:16 $
 *
 *  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 _DBAUI_LISTVIEWITEMS_HXX_
#include "listviewitems.hxx"
#endif

//........................................................................
namespace dbaui
{
//........................................................................

    //========================================================================
    // class OBoldListboxString
    //========================================================================
    //------------------------------------------------------------------------
    void OBoldListboxString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* _pViewData)
    {
        SvLBoxString::InitViewData(pView,pEntry, _pViewData);
        if (!_pViewData)
            _pViewData = pView->GetViewDataItem( pEntry, this );

        Font aOldFont( pView->GetFont());
        Font aFont( aOldFont );
        aFont.SetWeight(WEIGHT_BOLD);
        pView->SetFont( aFont );

        _pViewData->aSize = Size(pView->GetTextWidth(GetText()), pView->GetTextHeight());
        pView->SetFont( aOldFont );
    }

    //------------------------------------------------------------------------
    USHORT OBoldListboxString::IsA()
    {
        return SV_ITEM_ID_BOLDLBSTRING;
    }

    //------------------------------------------------------------------------
    void OBoldListboxString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry )
    {
        if (m_bEmphasized)
        {
            Font aOldFont( rDev.GetFont());
            Font aFont( aOldFont );
            aFont.SetWeight(WEIGHT_BOLD);
            rDev.SetFont( aFont );

            Point aPos(rPos);
            rDev.DrawText( aPos, GetText() );
            rDev.SetFont( aOldFont );
        }
        else
            SvLBoxString::Paint(rPos, rDev, nFlags, pEntry);
    }

//........................................................................
}   // namespace dbaui
//........................................................................

<|endoftext|>