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

#include "browser/inspectable_web_contents_impl.h"

#include "browser/browser_client.h"
#include "browser/browser_context.h"
#include "browser/browser_main_parts.h"
#include "browser/inspectable_web_contents_view.h"

#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_view_host.h"

namespace brightray {

namespace {

const char kDockSidePref[] = "brightray.devtools.dockside";

}

// Implemented separately on each platform.
InspectableWebContentsView* CreateInspectableContentsView(InspectableWebContentsImpl*);

void InspectableWebContentsImpl::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterStringPref(kDockSidePref, "bottom");
}

InspectableWebContentsImpl::InspectableWebContentsImpl(content::WebContents* web_contents)
    : web_contents_(web_contents) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  dock_side_ = context->prefs()->GetString(kDockSidePref);

  view_.reset(CreateInspectableContentsView(this));
}

InspectableWebContentsImpl::~InspectableWebContentsImpl() {
}

InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
  return view_.get();
}

content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
  return web_contents_.get();
}

void InspectableWebContentsImpl::ShowDevTools() {
  if (!devtools_web_contents_) {
    devtools_web_contents_.reset(content::WebContents::Create(content::WebContents::CreateParams(web_contents_->GetBrowserContext())));
    Observe(devtools_web_contents_.get());
    devtools_web_contents_->SetDelegate(this);

    agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents_->GetRenderViewHost());
    frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost(devtools_web_contents_.get(), this));

    auto handler = BrowserClient::Get()->browser_main_parts()->devtools_http_handler();
    auto url = handler->GetFrontendURL(nullptr);
    devtools_web_contents_->GetController().LoadURL(url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
  }

  view_->SetDockSide(dock_side_);
  view_->ShowDevTools();
}

void InspectableWebContentsImpl::UpdateFrontendDockSide() {
  auto javascript = base::StringPrintf("InspectorFrontendAPI.setDockSide(\"%s\")", dock_side_.c_str());
  devtools_web_contents_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), ASCIIToUTF16(javascript));
}

void InspectableWebContentsImpl::ActivateWindow() {
}

void InspectableWebContentsImpl::ChangeAttachedWindowHeight(unsigned height) {
}

void InspectableWebContentsImpl::CloseWindow() {
  view_->CloseDevTools();
  devtools_web_contents_.reset();
  web_contents_->GetView()->Focus();
}

void InspectableWebContentsImpl::MoveWindow(int x, int y) {
}

void InspectableWebContentsImpl::SetDockSide(const std::string& side) {
  if (!view_->SetDockSide(side))
    return;

  dock_side_ = side;

  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  context->prefs()->SetString(kDockSidePref, side);

  UpdateFrontendDockSide();
}

void InspectableWebContentsImpl::OpenInNewTab(const std::string& url) {
}

void InspectableWebContentsImpl::SaveToFile(const std::string& url, const std::string& content, bool save_as) {
}

void InspectableWebContentsImpl::AppendToFile(const std::string& url, const std::string& content) {
}

void InspectableWebContentsImpl::RequestFileSystems() {
}

void InspectableWebContentsImpl::AddFileSystem() {
}

void InspectableWebContentsImpl::RemoveFileSystem(const std::string& file_system_path) {
}

void InspectableWebContentsImpl::InspectedContentsClosing() {
}

void InspectableWebContentsImpl::RenderViewCreated(content::RenderViewHost* render_view_host) {
  content::DevToolsClientHost::SetupDevToolsFrontendClient(web_contents()->GetRenderViewHost());
  content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent_host_, frontend_host_.get());
}

void InspectableWebContentsImpl::DidFinishLoad(int64, const GURL&, bool is_main_frame, content::RenderViewHost*) {
  if (!is_main_frame)
    return;

  UpdateFrontendDockSide();
}

void InspectableWebContentsImpl::WebContentsDestroyed(content::WebContents*) {
  content::DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
  Observe(nullptr);
  agent_host_ = nullptr;
  frontend_host_.reset();
}

void InspectableWebContentsImpl::HandleKeyboardEvent(content::WebContents* source, const content::NativeWebKeyboardEvent& event) {
  auto delegate = web_contents_->GetDelegate();
  if (delegate)
    delegate->HandleKeyboardEvent(source, event);
}

}
<commit_msg>Update for utf_string_conversions.h move in Chrome 29<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "browser/inspectable_web_contents_impl.h"

#include "browser/browser_client.h"
#include "browser/browser_context.h"
#include "browser/browser_main_parts.h"
#include "browser/inspectable_web_contents_view.h"

#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_view_host.h"

namespace brightray {

namespace {

const char kDockSidePref[] = "brightray.devtools.dockside";

}

// Implemented separately on each platform.
InspectableWebContentsView* CreateInspectableContentsView(InspectableWebContentsImpl*);

void InspectableWebContentsImpl::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterStringPref(kDockSidePref, "bottom");
}

InspectableWebContentsImpl::InspectableWebContentsImpl(content::WebContents* web_contents)
    : web_contents_(web_contents) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  dock_side_ = context->prefs()->GetString(kDockSidePref);

  view_.reset(CreateInspectableContentsView(this));
}

InspectableWebContentsImpl::~InspectableWebContentsImpl() {
}

InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
  return view_.get();
}

content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
  return web_contents_.get();
}

void InspectableWebContentsImpl::ShowDevTools() {
  if (!devtools_web_contents_) {
    devtools_web_contents_.reset(content::WebContents::Create(content::WebContents::CreateParams(web_contents_->GetBrowserContext())));
    Observe(devtools_web_contents_.get());
    devtools_web_contents_->SetDelegate(this);

    agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents_->GetRenderViewHost());
    frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost(devtools_web_contents_.get(), this));

    auto handler = BrowserClient::Get()->browser_main_parts()->devtools_http_handler();
    auto url = handler->GetFrontendURL(nullptr);
    devtools_web_contents_->GetController().LoadURL(url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
  }

  view_->SetDockSide(dock_side_);
  view_->ShowDevTools();
}

void InspectableWebContentsImpl::UpdateFrontendDockSide() {
  auto javascript = base::StringPrintf("InspectorFrontendAPI.setDockSide(\"%s\")", dock_side_.c_str());
  devtools_web_contents_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(), ASCIIToUTF16(javascript));
}

void InspectableWebContentsImpl::ActivateWindow() {
}

void InspectableWebContentsImpl::ChangeAttachedWindowHeight(unsigned height) {
}

void InspectableWebContentsImpl::CloseWindow() {
  view_->CloseDevTools();
  devtools_web_contents_.reset();
  web_contents_->GetView()->Focus();
}

void InspectableWebContentsImpl::MoveWindow(int x, int y) {
}

void InspectableWebContentsImpl::SetDockSide(const std::string& side) {
  if (!view_->SetDockSide(side))
    return;

  dock_side_ = side;

  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  context->prefs()->SetString(kDockSidePref, side);

  UpdateFrontendDockSide();
}

void InspectableWebContentsImpl::OpenInNewTab(const std::string& url) {
}

void InspectableWebContentsImpl::SaveToFile(const std::string& url, const std::string& content, bool save_as) {
}

void InspectableWebContentsImpl::AppendToFile(const std::string& url, const std::string& content) {
}

void InspectableWebContentsImpl::RequestFileSystems() {
}

void InspectableWebContentsImpl::AddFileSystem() {
}

void InspectableWebContentsImpl::RemoveFileSystem(const std::string& file_system_path) {
}

void InspectableWebContentsImpl::InspectedContentsClosing() {
}

void InspectableWebContentsImpl::RenderViewCreated(content::RenderViewHost* render_view_host) {
  content::DevToolsClientHost::SetupDevToolsFrontendClient(web_contents()->GetRenderViewHost());
  content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent_host_, frontend_host_.get());
}

void InspectableWebContentsImpl::DidFinishLoad(int64, const GURL&, bool is_main_frame, content::RenderViewHost*) {
  if (!is_main_frame)
    return;

  UpdateFrontendDockSide();
}

void InspectableWebContentsImpl::WebContentsDestroyed(content::WebContents*) {
  content::DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
  Observe(nullptr);
  agent_host_ = nullptr;
  frontend_host_.reset();
}

void InspectableWebContentsImpl::HandleKeyboardEvent(content::WebContents* source, const content::NativeWebKeyboardEvent& event) {
  auto delegate = web_contents_->GetDelegate();
  if (delegate)
    delegate->HandleKeyboardEvent(source, event);
}

}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software 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 "boost/python.hpp"

#include "Gaffer/Context.h"

#include "GafferDispatchBindings/ExecutableNodeBinding.h"

#include "GafferScene/OpenGLRender.h"
#include "GafferScene/InteractiveRender.h"
#include "GafferScene/Preview/InteractiveRender.h"

#include "GafferSceneBindings/RenderBinding.h"

using namespace boost::python;

using namespace Gaffer;
using namespace GafferBindings;
using namespace GafferDispatchBindings;
using namespace GafferScene;

namespace
{

class ExecutableRenderWrapper : public ExecutableNodeWrapper<ExecutableRender>
{

	public :

		ExecutableRenderWrapper( PyObject *self, const std::string &name )
			:	ExecutableNodeWrapper<ExecutableRender>( self, name )
		{
		}

		virtual IECore::RendererPtr createRenderer() const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_createRenderer" );
				if( f )
				{
					return extract<IECore::RendererPtr>( f() );
				}
			}
			throw IECore::Exception( "No _createRenderer method defined in Python." );
		}

		virtual void outputWorldProcedural( const ScenePlug *scene, IECore::Renderer *renderer ) const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_outputWorldProcedural" );
				if( f )
				{
					f( ScenePlugPtr( const_cast<ScenePlug *>( scene ) ), IECore::RendererPtr( renderer ) );
					return;
				}
			}
			return ExecutableRender::outputWorldProcedural( scene, renderer );
		}

		virtual std::string command() const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_command" );
				if( f )
				{
					return extract<std::string>( f() );
				}
			}
			return ExecutableRender::command();
		}

};

ContextPtr interactiveRenderGetContext( InteractiveRender &r )
{
	return r.getContext();
}

ContextPtr previewInteractiveRenderGetContext( Preview::InteractiveRender &r )
{
	return r.getContext();
}

} // namespace

void GafferSceneBindings::bindRender()
{

	ExecutableNodeClass<ExecutableRender, ExecutableRenderWrapper>();

	ExecutableNodeClass<OpenGLRender>();

	{
		scope s = GafferBindings::NodeClass<InteractiveRender>()
			.def( "getContext", &interactiveRenderGetContext )
			.def( "setContext", &InteractiveRender::setContext );

		enum_<InteractiveRender::State>( "State" )
			.value( "Stopped", InteractiveRender::Stopped )
			.value( "Running", InteractiveRender::Running )
			.value( "Paused", InteractiveRender::Paused )
		;
	}

	{
		object previewModule( borrowed( PyImport_AddModule( "GafferScene.Preview" ) ) );
		scope().attr( "Preview" ) = previewModule;

		scope previewScope( previewModule );

		scope s = GafferBindings::NodeClass<GafferScene::Preview::InteractiveRender>()
			.def( "getContext", &previewInteractiveRenderGetContext )
			.def( "setContext", &GafferScene::Preview::InteractiveRender::setContext );

		enum_<GafferScene::Preview::InteractiveRender::State>( "State" )
			.value( "Stopped", GafferScene::Preview::InteractiveRender::Stopped )
			.value( "Running", GafferScene::Preview::InteractiveRender::Running )
			.value( "Paused", GafferScene::Preview::InteractiveRender::Paused )
		;
	}

}
<commit_msg>GafferScene module : Bind IECoreScenePreview::Renderer.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software 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 "boost/python.hpp"

#include "Gaffer/Context.h"

#include "GafferDispatchBindings/ExecutableNodeBinding.h"

#include "GafferScene/OpenGLRender.h"
#include "GafferScene/InteractiveRender.h"
#include "GafferScene/Preview/InteractiveRender.h"
#include "GafferScene/Private/IECoreScenePreview/Renderer.h"

#include "GafferSceneBindings/RenderBinding.h"

using namespace boost::python;

using namespace IECoreScenePreview;
using namespace Gaffer;
using namespace GafferBindings;
using namespace GafferDispatchBindings;
using namespace GafferScene;

namespace
{

class ExecutableRenderWrapper : public ExecutableNodeWrapper<ExecutableRender>
{

	public :

		ExecutableRenderWrapper( PyObject *self, const std::string &name )
			:	ExecutableNodeWrapper<ExecutableRender>( self, name )
		{
		}

		virtual IECore::RendererPtr createRenderer() const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_createRenderer" );
				if( f )
				{
					return extract<IECore::RendererPtr>( f() );
				}
			}
			throw IECore::Exception( "No _createRenderer method defined in Python." );
		}

		virtual void outputWorldProcedural( const ScenePlug *scene, IECore::Renderer *renderer ) const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_outputWorldProcedural" );
				if( f )
				{
					f( ScenePlugPtr( const_cast<ScenePlug *>( scene ) ), IECore::RendererPtr( renderer ) );
					return;
				}
			}
			return ExecutableRender::outputWorldProcedural( scene, renderer );
		}

		virtual std::string command() const
		{
			if( this->isSubclassed() )
			{
				IECorePython::ScopedGILLock gilLock;
				boost::python::object f = this->methodOverride( "_command" );
				if( f )
				{
					return extract<std::string>( f() );
				}
			}
			return ExecutableRender::command();
		}

};

ContextPtr interactiveRenderGetContext( InteractiveRender &r )
{
	return r.getContext();
}

ContextPtr previewInteractiveRenderGetContext( Preview::InteractiveRender &r )
{
	return r.getContext();
}

list rendererTypes()
{
	std::vector<IECore::InternedString> t = Renderer::types();
	list result;
	for( std::vector<IECore::InternedString>::const_iterator it = t.begin(), eIt = t.end(); it != eIt; ++it )
	{
		result.append( it->c_str() );
	}
	return result;
}

IECoreScenePreview::Renderer::ObjectInterfacePtr rendererObject1( Renderer &renderer, const std::string &name, const IECore::Object *object )
{
	return renderer.object( name, object );
}

IECoreScenePreview::Renderer::ObjectInterfacePtr rendererObject2( Renderer &renderer, const std::string &name, object pythonSamples, object pythonTimes )
{
	std::vector<const IECore::Object *> samples;
	container_utils::extend_container( samples, pythonSamples );

	std::vector<float> times;
	container_utils::extend_container( times, pythonTimes );

	return renderer.object( name, samples, times );
}

void objectInterfaceTransform1( Renderer::ObjectInterface &objectInterface, const Imath::M44f &transform )
{
	objectInterface.transform( transform );
}

void objectInterfaceTransform2( Renderer::ObjectInterface &objectInterface, object pythonSamples, object pythonTimes )
{
	std::vector<Imath::M44f> samples;
	container_utils::extend_container( samples, pythonSamples );

	std::vector<float> times;
	container_utils::extend_container( times, pythonTimes );

	return objectInterface.transform( samples, times );
}

} // namespace

void GafferSceneBindings::bindRender()
{

	ExecutableNodeClass<ExecutableRender, ExecutableRenderWrapper>();

	ExecutableNodeClass<OpenGLRender>();

	{
		scope s = GafferBindings::NodeClass<InteractiveRender>()
			.def( "getContext", &interactiveRenderGetContext )
			.def( "setContext", &InteractiveRender::setContext );

		enum_<InteractiveRender::State>( "State" )
			.value( "Stopped", InteractiveRender::Stopped )
			.value( "Running", InteractiveRender::Running )
			.value( "Paused", InteractiveRender::Paused )
		;
	}

	{
		object previewModule( borrowed( PyImport_AddModule( "GafferScene.Preview" ) ) );
		scope().attr( "Preview" ) = previewModule;

		scope previewScope( previewModule );

		scope s = GafferBindings::NodeClass<GafferScene::Preview::InteractiveRender>()
			.def( "getContext", &previewInteractiveRenderGetContext )
			.def( "setContext", &GafferScene::Preview::InteractiveRender::setContext );

		enum_<GafferScene::Preview::InteractiveRender::State>( "State" )
			.value( "Stopped", GafferScene::Preview::InteractiveRender::Stopped )
			.value( "Running", GafferScene::Preview::InteractiveRender::Running )
			.value( "Paused", GafferScene::Preview::InteractiveRender::Paused )
		;
	}

	{
		object privateModule( borrowed( PyImport_AddModule( "GafferScene.Private" ) ) );
		scope().attr( "Private" ) = privateModule;

		object ieCoreScenePreviewModule( borrowed( PyImport_AddModule( "GafferScene.Private.IECoreScenePreview" ) ) );
		scope().attr( "Private" ).attr( "IECoreScenePreview" ) = ieCoreScenePreviewModule;

		scope previewScope( ieCoreScenePreviewModule );

		IECorePython::RefCountedClass<Renderer, IECore::RefCounted> renderer( "Renderer" );

		{
			scope rendererScope( renderer );

			enum_<Renderer::RenderType>( "RenderType" )
				.value( "Batch", Renderer::Batch )
				.value( "SceneDescription", Renderer::SceneDescription )
				.value( "Interactive", Renderer::Interactive )
			;

			IECorePython::RefCountedClass<Renderer::AttributesInterface, IECore::RefCounted>( "AttributesInterface" );

			IECorePython::RefCountedClass<Renderer::ObjectInterface, IECore::RefCounted>( "ObjectInterface" )
				.def( "transform", objectInterfaceTransform1 )
				.def( "transform", objectInterfaceTransform2 )
				.def( "attributes", &Renderer::ObjectInterface::attributes )
			;
		}

		renderer

			.def( "types", &rendererTypes )
			.staticmethod( "types" )
			.def( "create", &Renderer::create, ( arg( "type" ), arg( "renderType" ) = Renderer::Batch, arg( "fileName" ) = "" ) )
			.staticmethod( "create" )

			.def( "option", &Renderer::option )
			.def( "output", &Renderer::output )

			.def( "attributes", &Renderer::attributes )

			.def( "camera", &Renderer::camera )
			.def( "light", &Renderer::light )

			.def( "object", &rendererObject1 )
			.def( "object", &rendererObject2 )

			.def( "render", &Renderer::render )
			.def( "pause", &Renderer::pause )

		;

	}

}
<|endoftext|>


<commit_before>/**
 * \ file InSndFilter.cpp
 */

#include <ATK/IO/libsndfile/InSndFileFilter.h>
#include <ATK/IO/InWavFilter.h>

#include <ATK/config.h>

#include <ATK/Tools/VolumeFilter.h>
#include <ATK/Tools/SumFilter.h>

#include <ATK/Mock/TriangleCheckerFilter.h>

#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#define PROCESSSIZE (1024)

BOOST_AUTO_TEST_CASE( InSndFileFilter_InFloat_1k_test )
{
  ATK::InSndFileFilter<float> generator(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");

  ATK::InWavFilter<float> filter(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::VolumeFilter<float> gainfilter;
  gainfilter.set_input_sampling_rate(48000);
  gainfilter.set_volume(-1);

  ATK::SumFilter<float> sumfilter;
  sumfilter.set_input_sampling_rate(48000);

  ATK::TriangleCheckerFilter<float> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  gainfilter.set_input_port(0, &generator, 0);
  sumfilter.set_input_port(0, &gainfilter, 0);
  sumfilter.set_input_port(1, &filter, 0);

  checker.set_input_port(0, &sumfilter, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InFloat_1k2k_test )
{
  ATK::InSndFileFilter<float> generator(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");

  ATK::VolumeFilter<float> gainfilter1;
  gainfilter1.set_input_sampling_rate(48000);
  gainfilter1.set_volume(-1);
  gainfilter1.set_input_port(0, &generator, 0);

  ATK::VolumeFilter<float> gainfilter2;
  gainfilter2.set_input_sampling_rate(48000);
  gainfilter2.set_volume(-1);
  gainfilter2.set_input_port(0, &generator, 1);

  ATK::InWavFilter<float> filter(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::SumFilter<float> sumfilter1;
  sumfilter1.set_input_sampling_rate(48000);
  sumfilter1.set_input_port(0, &gainfilter1, 0);
  sumfilter1.set_input_port(1, &filter, 0);

  ATK::SumFilter<float> sumfilter2;
  sumfilter2.set_input_sampling_rate(48000);
  sumfilter2.set_input_port(0, &gainfilter2, 0);
  sumfilter2.set_input_port(1, &filter, 1);

  ATK::SumFilter<float> sumfilter3;
  sumfilter3.set_input_sampling_rate(48000);
  sumfilter3.set_input_port(0, &sumfilter1, 0);
  sumfilter3.set_input_port(1, &sumfilter2, 0);

  ATK::TriangleCheckerFilter<float> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  checker.set_input_port(0, &sumfilter3, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InDouble_1k_test )
{
  ATK::InSndFileFilter<double> generator(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");

  ATK::InWavFilter<double> filter(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::VolumeFilter<double> gainfilter;
  gainfilter.set_input_sampling_rate(48000);
  gainfilter.set_volume(-1);

  ATK::SumFilter<double> sumfilter;
  sumfilter.set_input_sampling_rate(48000);

  ATK::TriangleCheckerFilter<double> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  gainfilter.set_input_port(0, &generator, 0);
  sumfilter.set_input_port(0, &gainfilter, 0);
  sumfilter.set_input_port(1, &filter, 0);

  checker.set_input_port(0, &sumfilter, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InDouble_1k2k_test )
{
  ATK::InSndFileFilter<double> generator(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");

  ATK::VolumeFilter<double> gainfilter1;
  gainfilter1.set_input_sampling_rate(48000);
  gainfilter1.set_volume(-1);
  gainfilter1.set_input_port(0, &generator, 0);

  ATK::VolumeFilter<double> gainfilter2;
  gainfilter2.set_input_sampling_rate(48000);
  gainfilter2.set_volume(-1);
  gainfilter2.set_input_port(0, &generator, 1);

  ATK::InWavFilter<double> filter(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::SumFilter<double> sumfilter1;
  sumfilter1.set_input_sampling_rate(48000);
  sumfilter1.set_input_port(0, &gainfilter1, 0);
  sumfilter1.set_input_port(1, &filter, 0);

  ATK::SumFilter<double> sumfilter2;
  sumfilter2.set_input_sampling_rate(48000);
  sumfilter2.set_input_port(0, &gainfilter2, 0);
  sumfilter2.set_input_port(1, &filter, 1);

  ATK::SumFilter<double> sumfilter3;
  sumfilter3.set_input_sampling_rate(48000);
  sumfilter3.set_input_port(0, &sumfilter1, 0);
  sumfilter3.set_input_port(1, &sumfilter2, 0);

  ATK::TriangleCheckerFilter<double> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  checker.set_input_port(0, &sumfilter3, 0);

  checker.process(PROCESSSIZE);
}
<commit_msg>More checks on input frames (libsndfile)<commit_after>/**
 * \ file InSndFilter.cpp
 */

#include <ATK/IO/libsndfile/InSndFileFilter.h>
#include <ATK/IO/InWavFilter.h>

#include <ATK/config.h>

#include <ATK/Tools/VolumeFilter.h>
#include <ATK/Tools/SumFilter.h>

#include <ATK/Mock/TriangleCheckerFilter.h>

#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

const size_t PROCESSSIZE = 1024;

BOOST_AUTO_TEST_CASE( InSndFileFilter_InFloat_1k_test )
{
  ATK::InSndFileFilter<float> generator(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");
  BOOST_CHECK_EQUAL(generator.get_frames(), PROCESSSIZE);

  ATK::InWavFilter<float> filter(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::VolumeFilter<float> gainfilter;
  gainfilter.set_input_sampling_rate(48000);
  gainfilter.set_volume(-1);

  ATK::SumFilter<float> sumfilter;
  sumfilter.set_input_sampling_rate(48000);

  ATK::TriangleCheckerFilter<float> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  gainfilter.set_input_port(0, &generator, 0);
  sumfilter.set_input_port(0, &gainfilter, 0);
  sumfilter.set_input_port(1, &filter, 0);

  checker.set_input_port(0, &sumfilter, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InFloat_1k2k_test )
{
  ATK::InSndFileFilter<float> generator(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");

  ATK::VolumeFilter<float> gainfilter1;
  gainfilter1.set_input_sampling_rate(48000);
  gainfilter1.set_volume(-1);
  gainfilter1.set_input_port(0, &generator, 0);

  ATK::VolumeFilter<float> gainfilter2;
  gainfilter2.set_input_sampling_rate(48000);
  gainfilter2.set_volume(-1);
  gainfilter2.set_input_port(0, &generator, 1);

  ATK::InWavFilter<float> filter(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::SumFilter<float> sumfilter1;
  sumfilter1.set_input_sampling_rate(48000);
  sumfilter1.set_input_port(0, &gainfilter1, 0);
  sumfilter1.set_input_port(1, &filter, 0);

  ATK::SumFilter<float> sumfilter2;
  sumfilter2.set_input_sampling_rate(48000);
  sumfilter2.set_input_port(0, &gainfilter2, 0);
  sumfilter2.set_input_port(1, &filter, 1);

  ATK::SumFilter<float> sumfilter3;
  sumfilter3.set_input_sampling_rate(48000);
  sumfilter3.set_input_port(0, &sumfilter1, 0);
  sumfilter3.set_input_port(1, &sumfilter2, 0);

  ATK::TriangleCheckerFilter<float> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  checker.set_input_port(0, &sumfilter3, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InDouble_1k_test )
{
  ATK::InSndFileFilter<double> generator(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");

  ATK::InWavFilter<double> filter(ATK_SOURCE_TREE "/tests/data/sinus1k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::VolumeFilter<double> gainfilter;
  gainfilter.set_input_sampling_rate(48000);
  gainfilter.set_volume(-1);

  ATK::SumFilter<double> sumfilter;
  sumfilter.set_input_sampling_rate(48000);

  ATK::TriangleCheckerFilter<double> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  gainfilter.set_input_port(0, &generator, 0);
  sumfilter.set_input_port(0, &gainfilter, 0);
  sumfilter.set_input_port(1, &filter, 0);

  checker.set_input_port(0, &sumfilter, 0);

  checker.process(PROCESSSIZE);
}

BOOST_AUTO_TEST_CASE( InSndFileFilter_InDouble_1k2k_test )
{
  ATK::InSndFileFilter<double> generator(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");

  ATK::VolumeFilter<double> gainfilter1;
  gainfilter1.set_input_sampling_rate(48000);
  gainfilter1.set_volume(-1);
  gainfilter1.set_input_port(0, &generator, 0);

  ATK::VolumeFilter<double> gainfilter2;
  gainfilter2.set_input_sampling_rate(48000);
  gainfilter2.set_volume(-1);
  gainfilter2.set_input_port(0, &generator, 1);

  ATK::InWavFilter<double> filter(ATK_SOURCE_TREE "/tests/data/sinus1k2k.wav");
  filter.set_output_sampling_rate(48000);

  ATK::SumFilter<double> sumfilter1;
  sumfilter1.set_input_sampling_rate(48000);
  sumfilter1.set_input_port(0, &gainfilter1, 0);
  sumfilter1.set_input_port(1, &filter, 0);

  ATK::SumFilter<double> sumfilter2;
  sumfilter2.set_input_sampling_rate(48000);
  sumfilter2.set_input_port(0, &gainfilter2, 0);
  sumfilter2.set_input_port(1, &filter, 1);

  ATK::SumFilter<double> sumfilter3;
  sumfilter3.set_input_sampling_rate(48000);
  sumfilter3.set_input_port(0, &sumfilter1, 0);
  sumfilter3.set_input_port(1, &sumfilter2, 0);

  ATK::TriangleCheckerFilter<double> checker;
  checker.set_input_sampling_rate(48000);
  checker.set_amplitude(0);
  checker.set_frequency(1000);

  checker.set_input_port(0, &sumfilter3, 0);

  checker.process(PROCESSSIZE);
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////
// File:        lstmtraining.cpp
// Description: Training program for LSTM-based networks.
// Author:      Ray Smith
// Created:     Fri May 03 11:05:06 PST 2013
//
// (C) Copyright 2013, Google Inc.
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#ifdef GOOGLE_TESSERACT
#include "base/commandlineflags.h"
#endif
#include "commontraining.h"
#include "lstmtester.h"
#include "lstmtrainer.h"
#include "params.h"
#include "strngs.h"
#include "tprintf.h"
#include "unicharset_training_utils.h"

INT_PARAM_FLAG(debug_interval, 0, "How often to display the alignment.");
STRING_PARAM_FLAG(net_spec, "", "Network specification");
INT_PARAM_FLAG(net_mode, 192, "Controls network behavior.");
INT_PARAM_FLAG(perfect_sample_delay, 0,
               "How many imperfect samples between perfect ones.");
DOUBLE_PARAM_FLAG(target_error_rate, 0.01, "Final error rate in percent.");
DOUBLE_PARAM_FLAG(weight_range, 0.1, "Range of initial random weights.");
DOUBLE_PARAM_FLAG(learning_rate, 10.0e-4, "Weight factor for new deltas.");
DOUBLE_PARAM_FLAG(momentum, 0.5, "Decay factor for repeating deltas.");
DOUBLE_PARAM_FLAG(adam_beta, 0.999, "Decay factor for repeating deltas.");
INT_PARAM_FLAG(max_image_MB, 6000, "Max memory to use for images.");
STRING_PARAM_FLAG(continue_from, "", "Existing model to extend");
STRING_PARAM_FLAG(model_output, "lstmtrain", "Basename for output models");
STRING_PARAM_FLAG(train_listfile, "",
                  "File listing training files in lstmf training format.");
STRING_PARAM_FLAG(eval_listfile, "",
                  "File listing eval files in lstmf training format.");
BOOL_PARAM_FLAG(stop_training, false,
               "Just convert the training model to a runtime model.");
BOOL_PARAM_FLAG(convert_to_int, false,
                "Convert the recognition model to an integer model.");
BOOL_PARAM_FLAG(sequential_training, false,
                "Use the training files sequentially instead of round-robin.");
INT_PARAM_FLAG(append_index, -1, "Index in continue_from Network at which to"
               " attach the new network defined by net_spec");
BOOL_PARAM_FLAG(debug_network, false,
                "Get info on distribution of weight values");
INT_PARAM_FLAG(max_iterations, 0, "If set, exit after this many iterations");
STRING_PARAM_FLAG(traineddata, "",
                  "Combined Dawgs/Unicharset/Recoder for language model");
STRING_PARAM_FLAG(old_traineddata, "",
                  "When changing the character set, this specifies the old"
                  " character set that is to be replaced");
BOOL_PARAM_FLAG(randomly_rotate, false,
                "Train OSD and randomly turn training samples upside-down");

// Number of training images to train between calls to MaintainCheckpoints.
const int kNumPagesPerBatch = 100;

// Apart from command-line flags, input is a collection of lstmf files, that
// were previously created using tesseract with the lstm.train config file.
// The program iterates over the inputs, feeding the data to the network,
// until the error rate reaches a specified target or max_iterations is reached.
int main(int argc, char **argv) {
  tesseract::CheckSharedLibraryVersion();
  ParseArguments(&argc, &argv);
  // Purify the model name in case it is based on the network string.
  if (FLAGS_model_output.empty()) {
    tprintf("Must provide a --model_output!\n");
    return EXIT_FAILURE;
  }
  if (FLAGS_traineddata.empty()) {
    tprintf("Must provide a --traineddata see training wiki\n");
    return EXIT_FAILURE;
  }
  STRING model_output = FLAGS_model_output.c_str();
  for (int i = 0; i < model_output.length(); ++i) {
    if (model_output[i] == '[' || model_output[i] == ']')
      model_output[i] = '-';
    if (model_output[i] == '(' || model_output[i] == ')')
      model_output[i] = '_';
  }

  // Check write permissions.
  STRING test_file = FLAGS_model_output.c_str();
  test_file += "_wtest";
  FILE* f = fopen(test_file.c_str(), "wb");
  if (f != nullptr) {
    fclose(f);
    remove(test_file.c_str());
  } else {
    tprintf("Error, model output cannot be written: %s\n", strerror(errno));
    return EXIT_FAILURE;
  }

  // Setup the trainer.
  STRING checkpoint_file = FLAGS_model_output.c_str();
  checkpoint_file += "_checkpoint";
  STRING checkpoint_bak = checkpoint_file + ".bak";
  tesseract::LSTMTrainer trainer(
      nullptr, nullptr, nullptr, nullptr, FLAGS_model_output.c_str(),
      checkpoint_file.c_str(), FLAGS_debug_interval,
      static_cast<int64_t>(FLAGS_max_image_MB) * 1048576);
  trainer.InitCharSet(FLAGS_traineddata.c_str());

  // Reading something from an existing model doesn't require many flags,
  // so do it now and exit.
  if (FLAGS_stop_training || FLAGS_debug_network) {
    if (!trainer.TryLoadingCheckpoint(FLAGS_continue_from.c_str(), nullptr)) {
      tprintf("Failed to read continue from: %s\n",
              FLAGS_continue_from.c_str());
      return EXIT_FAILURE;
    }
    if (FLAGS_debug_network) {
      trainer.DebugNetwork();
    } else {
      if (FLAGS_convert_to_int) trainer.ConvertToInt();
      if (!trainer.SaveTraineddata(FLAGS_model_output.c_str())) {
        tprintf("Failed to write recognition model : %s\n",
                FLAGS_model_output.c_str());
      }
    }
    return EXIT_SUCCESS;
  }

  // Get the list of files to process.
  if (FLAGS_train_listfile.empty()) {
    tprintf("Must supply a list of training filenames! --train_listfile\n");
    return EXIT_FAILURE;
  }
  GenericVector<STRING> filenames;
  if (!tesseract::LoadFileLinesToStrings(FLAGS_train_listfile.c_str(),
                                         &filenames)) {
    tprintf("Failed to load list of training filenames from %s\n",
            FLAGS_train_listfile.c_str());
    return EXIT_FAILURE;
  }

  // Checkpoints always take priority if they are available.
  if (trainer.TryLoadingCheckpoint(checkpoint_file.string(), nullptr) ||
      trainer.TryLoadingCheckpoint(checkpoint_bak.string(), nullptr)) {
    tprintf("Successfully restored trainer from %s\n",
            checkpoint_file.string());
  } else {
    if (!FLAGS_continue_from.empty()) {
      // Load a past model file to improve upon.
      if (!trainer.TryLoadingCheckpoint(FLAGS_continue_from.c_str(),
                                        FLAGS_append_index >= 0
                                            ? FLAGS_continue_from.c_str()
                                            : FLAGS_old_traineddata.c_str())) {
        tprintf("Failed to continue from: %s\n", FLAGS_continue_from.c_str());
        return EXIT_FAILURE;
      }
      tprintf("Continuing from %s\n", FLAGS_continue_from.c_str());
      trainer.InitIterations();
    }
    if (FLAGS_continue_from.empty() || FLAGS_append_index >= 0) {
      if (FLAGS_append_index >= 0) {
        tprintf("Appending a new network to an old one!!");
        if (FLAGS_continue_from.empty()) {
          tprintf("Must set --continue_from for appending!\n");
          return EXIT_FAILURE;
        }
      }
      // We are initializing from scratch.
      if (!trainer.InitNetwork(FLAGS_net_spec.c_str(), FLAGS_append_index,
                               FLAGS_net_mode, FLAGS_weight_range,
                               FLAGS_learning_rate, FLAGS_momentum,
                               FLAGS_adam_beta)) {
        tprintf("Failed to create network from spec: %s\n",
                FLAGS_net_spec.c_str());
        return EXIT_FAILURE;
      }
      trainer.set_perfect_delay(FLAGS_perfect_sample_delay);
    }
  }
  if (!trainer.LoadAllTrainingData(filenames,
                                   FLAGS_sequential_training
                                       ? tesseract::CS_SEQUENTIAL
                                       : tesseract::CS_ROUND_ROBIN,
                                   FLAGS_randomly_rotate)) {
    tprintf("Load of images failed!!\n");
    return EXIT_FAILURE;
  }

  tesseract::LSTMTester tester(static_cast<int64_t>(FLAGS_max_image_MB) *
                               1048576);
  tesseract::TestCallback tester_callback = nullptr;
  if (!FLAGS_eval_listfile.empty()) {
    if (!tester.LoadAllEvalData(FLAGS_eval_listfile.c_str())) {
      tprintf("Failed to load eval data from: %s\n",
              FLAGS_eval_listfile.c_str());
      return EXIT_FAILURE;
    }
    tester_callback =
        NewPermanentTessCallback(&tester, &tesseract::LSTMTester::RunEvalAsync);
  }
  do {
    // Train a few.
    int iteration = trainer.training_iteration();
    for (int target_iteration = iteration + kNumPagesPerBatch;
         iteration < target_iteration &&
         (iteration < FLAGS_max_iterations || FLAGS_max_iterations == 0);
         iteration = trainer.training_iteration()) {
      trainer.TrainOnLine(&trainer, false);
    }
    STRING log_str;
    trainer.MaintainCheckpoints(tester_callback, &log_str);
    tprintf("%s\n", log_str.string());
  } while (trainer.best_error_rate() > FLAGS_target_error_rate &&
           (trainer.training_iteration() < FLAGS_max_iterations ||
            FLAGS_max_iterations == 0));
  delete tester_callback;
  tprintf("Finished! Error rate = %g\n", trainer.best_error_rate());
  return EXIT_SUCCESS;
} /* main */
<commit_msg>lstmtraining: Remove dead code for purified model name<commit_after>///////////////////////////////////////////////////////////////////////
// File:        lstmtraining.cpp
// Description: Training program for LSTM-based networks.
// Author:      Ray Smith
// Created:     Fri May 03 11:05:06 PST 2013
//
// (C) Copyright 2013, Google Inc.
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#ifdef GOOGLE_TESSERACT
#include "base/commandlineflags.h"
#endif
#include "commontraining.h"
#include "lstmtester.h"
#include "lstmtrainer.h"
#include "params.h"
#include "strngs.h"
#include "tprintf.h"
#include "unicharset_training_utils.h"

INT_PARAM_FLAG(debug_interval, 0, "How often to display the alignment.");
STRING_PARAM_FLAG(net_spec, "", "Network specification");
INT_PARAM_FLAG(net_mode, 192, "Controls network behavior.");
INT_PARAM_FLAG(perfect_sample_delay, 0,
               "How many imperfect samples between perfect ones.");
DOUBLE_PARAM_FLAG(target_error_rate, 0.01, "Final error rate in percent.");
DOUBLE_PARAM_FLAG(weight_range, 0.1, "Range of initial random weights.");
DOUBLE_PARAM_FLAG(learning_rate, 10.0e-4, "Weight factor for new deltas.");
DOUBLE_PARAM_FLAG(momentum, 0.5, "Decay factor for repeating deltas.");
DOUBLE_PARAM_FLAG(adam_beta, 0.999, "Decay factor for repeating deltas.");
INT_PARAM_FLAG(max_image_MB, 6000, "Max memory to use for images.");
STRING_PARAM_FLAG(continue_from, "", "Existing model to extend");
STRING_PARAM_FLAG(model_output, "lstmtrain", "Basename for output models");
STRING_PARAM_FLAG(train_listfile, "",
                  "File listing training files in lstmf training format.");
STRING_PARAM_FLAG(eval_listfile, "",
                  "File listing eval files in lstmf training format.");
BOOL_PARAM_FLAG(stop_training, false,
               "Just convert the training model to a runtime model.");
BOOL_PARAM_FLAG(convert_to_int, false,
                "Convert the recognition model to an integer model.");
BOOL_PARAM_FLAG(sequential_training, false,
                "Use the training files sequentially instead of round-robin.");
INT_PARAM_FLAG(append_index, -1, "Index in continue_from Network at which to"
               " attach the new network defined by net_spec");
BOOL_PARAM_FLAG(debug_network, false,
                "Get info on distribution of weight values");
INT_PARAM_FLAG(max_iterations, 0, "If set, exit after this many iterations");
STRING_PARAM_FLAG(traineddata, "",
                  "Combined Dawgs/Unicharset/Recoder for language model");
STRING_PARAM_FLAG(old_traineddata, "",
                  "When changing the character set, this specifies the old"
                  " character set that is to be replaced");
BOOL_PARAM_FLAG(randomly_rotate, false,
                "Train OSD and randomly turn training samples upside-down");

// Number of training images to train between calls to MaintainCheckpoints.
const int kNumPagesPerBatch = 100;

// Apart from command-line flags, input is a collection of lstmf files, that
// were previously created using tesseract with the lstm.train config file.
// The program iterates over the inputs, feeding the data to the network,
// until the error rate reaches a specified target or max_iterations is reached.
int main(int argc, char **argv) {
  tesseract::CheckSharedLibraryVersion();
  ParseArguments(&argc, &argv);
  if (FLAGS_model_output.empty()) {
    tprintf("Must provide a --model_output!\n");
    return EXIT_FAILURE;
  }
  if (FLAGS_traineddata.empty()) {
    tprintf("Must provide a --traineddata see training wiki\n");
    return EXIT_FAILURE;
  }

  // Check write permissions.
  STRING test_file = FLAGS_model_output.c_str();
  test_file += "_wtest";
  FILE* f = fopen(test_file.c_str(), "wb");
  if (f != nullptr) {
    fclose(f);
    remove(test_file.c_str());
  } else {
    tprintf("Error, model output cannot be written: %s\n", strerror(errno));
    return EXIT_FAILURE;
  }

  // Setup the trainer.
  STRING checkpoint_file = FLAGS_model_output.c_str();
  checkpoint_file += "_checkpoint";
  STRING checkpoint_bak = checkpoint_file + ".bak";
  tesseract::LSTMTrainer trainer(
      nullptr, nullptr, nullptr, nullptr, FLAGS_model_output.c_str(),
      checkpoint_file.c_str(), FLAGS_debug_interval,
      static_cast<int64_t>(FLAGS_max_image_MB) * 1048576);
  trainer.InitCharSet(FLAGS_traineddata.c_str());

  // Reading something from an existing model doesn't require many flags,
  // so do it now and exit.
  if (FLAGS_stop_training || FLAGS_debug_network) {
    if (!trainer.TryLoadingCheckpoint(FLAGS_continue_from.c_str(), nullptr)) {
      tprintf("Failed to read continue from: %s\n",
              FLAGS_continue_from.c_str());
      return EXIT_FAILURE;
    }
    if (FLAGS_debug_network) {
      trainer.DebugNetwork();
    } else {
      if (FLAGS_convert_to_int) trainer.ConvertToInt();
      if (!trainer.SaveTraineddata(FLAGS_model_output.c_str())) {
        tprintf("Failed to write recognition model : %s\n",
                FLAGS_model_output.c_str());
      }
    }
    return EXIT_SUCCESS;
  }

  // Get the list of files to process.
  if (FLAGS_train_listfile.empty()) {
    tprintf("Must supply a list of training filenames! --train_listfile\n");
    return EXIT_FAILURE;
  }
  GenericVector<STRING> filenames;
  if (!tesseract::LoadFileLinesToStrings(FLAGS_train_listfile.c_str(),
                                         &filenames)) {
    tprintf("Failed to load list of training filenames from %s\n",
            FLAGS_train_listfile.c_str());
    return EXIT_FAILURE;
  }

  // Checkpoints always take priority if they are available.
  if (trainer.TryLoadingCheckpoint(checkpoint_file.string(), nullptr) ||
      trainer.TryLoadingCheckpoint(checkpoint_bak.string(), nullptr)) {
    tprintf("Successfully restored trainer from %s\n",
            checkpoint_file.string());
  } else {
    if (!FLAGS_continue_from.empty()) {
      // Load a past model file to improve upon.
      if (!trainer.TryLoadingCheckpoint(FLAGS_continue_from.c_str(),
                                        FLAGS_append_index >= 0
                                            ? FLAGS_continue_from.c_str()
                                            : FLAGS_old_traineddata.c_str())) {
        tprintf("Failed to continue from: %s\n", FLAGS_continue_from.c_str());
        return EXIT_FAILURE;
      }
      tprintf("Continuing from %s\n", FLAGS_continue_from.c_str());
      trainer.InitIterations();
    }
    if (FLAGS_continue_from.empty() || FLAGS_append_index >= 0) {
      if (FLAGS_append_index >= 0) {
        tprintf("Appending a new network to an old one!!");
        if (FLAGS_continue_from.empty()) {
          tprintf("Must set --continue_from for appending!\n");
          return EXIT_FAILURE;
        }
      }
      // We are initializing from scratch.
      if (!trainer.InitNetwork(FLAGS_net_spec.c_str(), FLAGS_append_index,
                               FLAGS_net_mode, FLAGS_weight_range,
                               FLAGS_learning_rate, FLAGS_momentum,
                               FLAGS_adam_beta)) {
        tprintf("Failed to create network from spec: %s\n",
                FLAGS_net_spec.c_str());
        return EXIT_FAILURE;
      }
      trainer.set_perfect_delay(FLAGS_perfect_sample_delay);
    }
  }
  if (!trainer.LoadAllTrainingData(filenames,
                                   FLAGS_sequential_training
                                       ? tesseract::CS_SEQUENTIAL
                                       : tesseract::CS_ROUND_ROBIN,
                                   FLAGS_randomly_rotate)) {
    tprintf("Load of images failed!!\n");
    return EXIT_FAILURE;
  }

  tesseract::LSTMTester tester(static_cast<int64_t>(FLAGS_max_image_MB) *
                               1048576);
  tesseract::TestCallback tester_callback = nullptr;
  if (!FLAGS_eval_listfile.empty()) {
    if (!tester.LoadAllEvalData(FLAGS_eval_listfile.c_str())) {
      tprintf("Failed to load eval data from: %s\n",
              FLAGS_eval_listfile.c_str());
      return EXIT_FAILURE;
    }
    tester_callback =
        NewPermanentTessCallback(&tester, &tesseract::LSTMTester::RunEvalAsync);
  }
  do {
    // Train a few.
    int iteration = trainer.training_iteration();
    for (int target_iteration = iteration + kNumPagesPerBatch;
         iteration < target_iteration &&
         (iteration < FLAGS_max_iterations || FLAGS_max_iterations == 0);
         iteration = trainer.training_iteration()) {
      trainer.TrainOnLine(&trainer, false);
    }
    STRING log_str;
    trainer.MaintainCheckpoints(tester_callback, &log_str);
    tprintf("%s\n", log_str.string());
  } while (trainer.best_error_rate() > FLAGS_target_error_rate &&
           (trainer.training_iteration() < FLAGS_max_iterations ||
            FLAGS_max_iterations == 0));
  delete tester_callback;
  tprintf("Finished! Error rate = %g\n", trainer.best_error_rate());
  return EXIT_SUCCESS;
} /* main */
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <qi/log.hpp>
#include <cerrno>

#include <boost/asio.hpp>

#include <boost/lexical_cast.hpp>

#include "transportserver.hpp"
#include "transportsocket.hpp"
#include "tcptransportsocket.hpp"

#include <qi/eventloop.hpp>

#include "transportserverasio_p.hpp"

qiLogCategory("qimessaging.transportserver");

namespace qi
{
  const int ifsMonitoringTimeout = 5 * 1000 * 1000; // in usec

  void _onAccept(TransportServerImplPtr p,
                 const boost::system::error_code& erc,
#ifdef WITH_SSL
                 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>* s
#else
                 boost::asio::ip::tcp::socket* s
#endif
                 )
  {
    boost::shared_ptr<TransportServerAsioPrivate> ts = boost::dynamic_pointer_cast<TransportServerAsioPrivate>(p);
    ts->onAccept(erc, s);
  }

  void TransportServerAsioPrivate::onAccept(const boost::system::error_code& erc,
#ifdef WITH_SSL
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket>* s
#else
    boost::asio::ip::tcp::socket* s
#endif
    )
  {
    qiLogDebug() << this << " onAccept";
    if (!_live)
    {
      delete s;
      return;
    }
    if (erc)
    {
      qiLogDebug() << "accept error " << erc.message();
      delete s;
      self->acceptError(erc.value());
      delete _acceptor;
      _acceptor = 0;
      return;
    }
    qi::TransportSocketPtr socket = qi::TcpTransportSocketPtr(new TcpTransportSocket(context, _ssl, s));
    self->newConnection(socket);

    if (socket.unique()) {
      qiLogError() << "bug: socket not stored by the newConnection handler (usecount:" << socket.use_count() << ")";
    }
#ifdef WITH_SSL
    _s = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(_acceptor->get_io_service(), _sslContext);
#else
    _s = new boost::asio::ip::tcp::socket(_acceptor->get_io_service());
#endif
    _acceptor->async_accept(_s->lowest_layer(),
                           boost::bind(_onAccept, shared_from_this(), _1, _s));
  }

  void TransportServerAsioPrivate::close() {
    qiLogDebug() << this << " close";
    try
    {
      _asyncEndpoints.cancel();
    }
    catch (const std::runtime_error& e)
    {
      qiLogDebug() << e.what();
    }

    _live = false;
    _acceptor->close();
  }

  /*
   * This asynchronous call will keep a shared ptr on the object to prevent
   * its destruction.
   */
  void _updateEndpoints(TransportServerImplPtr p)
  {
    boost::shared_ptr<TransportServerAsioPrivate> ts = boost::dynamic_pointer_cast<TransportServerAsioPrivate>(p);
    ts->updateEndpoints();
  }

  /*
   * This function is used to detect and update endpoints when the transport
   * server is listening on 0.0.0.0.
   */
  void TransportServerAsioPrivate::updateEndpoints()
  {
    if (!_live)
    {
      return;
    }

    // TODO: implement OS networking notifications

    qiLogDebug() << "Checking endpoints...";
    std::vector<qi::Url> currentEndpoints;

    std::map<std::string, std::vector<std::string> > ifsMap = qi::os::hostIPAddrs();
    if (ifsMap.empty())
    {
      const char* s = "Cannot get host addresses";
      qiLogWarning() << s;
    }

    std::string protocol = _ssl ? "tcps://" : "tcp://";

    {
      for (std::map<std::string, std::vector<std::string> >::iterator interfaceIt = ifsMap.begin();
           interfaceIt != ifsMap.end();
           ++interfaceIt)
      {
        for (std::vector<std::string>::iterator addressIt = (*interfaceIt).second.begin();
             addressIt != (*interfaceIt).second.end();
             ++addressIt)
        {
          std::stringstream ss;
          ss << protocol << (*addressIt) << ":" << _port;
          currentEndpoints.push_back(ss.str());
        }
      }
    }

    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      if (_endpoints.size() != currentEndpoints.size() ||
          !std::equal(_endpoints.begin(), _endpoints.end(), currentEndpoints.begin()))
      {
        std::stringstream ss;
        std::vector<qi::Url>::iterator it;
        for (it = currentEndpoints.begin(); it != currentEndpoints.end(); ++it)
          ss << "ep: " << it->str() << std::endl;
        qiLogVerbose() << "Updating endpoints..." << this << std::endl << ss.str();
        _endpoints = currentEndpoints;
        _self->endpointsChanged();
      }

    }

    _asyncEndpoints = context->async(boost::bind(_updateEndpoints, shared_from_this()),
                                     ifsMonitoringTimeout);
  }

  qi::Future<void> TransportServerAsioPrivate::listen(const qi::Url& url)
  {
    qi::Url listenUrl = url;
    _ssl = listenUrl.protocol() == "tcps";
    using namespace boost::asio;
#ifndef ANDROID
    // resolve endpoint
    ip::tcp::resolver r(_acceptor->get_io_service());
    ip::tcp::resolver::query q(listenUrl.host(), boost::lexical_cast<std::string>(listenUrl.port()),
                               boost::asio::ip::tcp::resolver::query::all_matching);
    ip::tcp::resolver::iterator it = r.resolve(q);
    if (it == ip::tcp::resolver::iterator())
    {
      const char* s = "Listen error: no endpoint.";
      qiLogError() << s;
      return qi::makeFutureError<void>(s);
    }
    ip::tcp::endpoint ep = *it;
#else
    ip::tcp::endpoint ep(boost::asio::ip::address::from_string(url.host()), url.port());
#endif // #ifndef ANDROID

    qiLogDebug() << "Will listen on " << ep.address().to_string() << ' ' << ep.port();
    _acceptor->open(ep.protocol());
#ifdef _WIN32
    boost::asio::socket_base::reuse_address option(false);
#else
    boost::asio::socket_base::reuse_address option(true);
    fcntl(_acceptor->native(), F_SETFD, FD_CLOEXEC);
#endif
    _acceptor->set_option(option);
    _acceptor->bind(ep);
    boost::system::error_code ec;
    _acceptor->listen(socket_base::max_connections, ec);
    if (ec)
    {
      qiLogError("qimessaging.server.listen") << ec.message();
      return qi::makeFutureError<void>(ec.message());
    }
    _port = _acceptor->local_endpoint().port();// already in host byte orde
    qiLogDebug() << "Effective port io_service" << _port;
    if (listenUrl.port() == 0)
    {
      listenUrl = Url(listenUrl.protocol() + "://" + listenUrl.host() + ":"
        + boost::lexical_cast<std::string>(_port));
    }

    /* Set endpoints */
    if (listenUrl.host() != "0.0.0.0")
    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      _endpoints.push_back(listenUrl.str());
    }
    else
    {
      updateEndpoints();
    }

    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      for (std::vector<qi::Url>::const_iterator it = _endpoints.begin();
           it != _endpoints.end();
           it++)
      {
        qiLogInfo() << "TransportServer will listen on: " << it->str();
      }
    }

#ifdef WITH_SSL
    if (_ssl)
    {
      if (self->_identityCertificate.empty() || self->_identityKey.empty())
      {
        const char* s = "SSL certificates missing, please call Session::setIdentity first";
        qiLogError("qimessaging.server.listen") << s;
        return qi::makeFutureError<void>(s);
      }

      _sslContext.set_options(
        boost::asio::ssl::context::default_workarounds
        | boost::asio::ssl::context::no_sslv2);
      _sslContext.use_certificate_chain_file(self->_identityCertificate.c_str());
      _sslContext.use_private_key_file(self->_identityKey.c_str(), boost::asio::ssl::context::pem);
    }

    _s = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(_acceptor->get_io_service(), _sslContext);
#else
    _s = new boost::asio::ip::tcp::socket(_acceptor->get_io_service());
#endif
    _acceptor->async_accept(_s->lowest_layer(),
      boost::bind(_onAccept, shared_from_this(), _1, _s));
    _connectionPromise.setValue(0);
    return _connectionPromise.future();
  }

  TransportServerAsioPrivate::TransportServerAsioPrivate(TransportServer* self,
                                                                 EventLoop* ctx)
    : TransportServerImpl(self, ctx)
    , _self(self)
    , _acceptor(new boost::asio::ip::tcp::acceptor(*(boost::asio::io_service*)ctx->nativeHandle()))
    , _live(true)
#ifdef WITH_SSL
    , _sslContext(*(boost::asio::io_service*)ctx->nativeHandle(), boost::asio::ssl::context::sslv23)
#endif
    , _ssl(false)
  {
  }

  TransportServerAsioPrivate::~TransportServerAsioPrivate()
  {
    delete _acceptor;
    _acceptor = 0;
  }
}
<commit_msg>TransportServerAsio: fix segfault on close()<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <qi/log.hpp>
#include <cerrno>

#include <boost/asio.hpp>

#include <boost/lexical_cast.hpp>

#include "transportserver.hpp"
#include "transportsocket.hpp"
#include "tcptransportsocket.hpp"

#include <qi/eventloop.hpp>

#include "transportserverasio_p.hpp"

qiLogCategory("qimessaging.transportserver");

namespace qi
{
  const int ifsMonitoringTimeout = 5 * 1000 * 1000; // in usec

  void _onAccept(TransportServerImplPtr p,
                 const boost::system::error_code& erc,
#ifdef WITH_SSL
                 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>* s
#else
                 boost::asio::ip::tcp::socket* s
#endif
                 )
  {
    boost::shared_ptr<TransportServerAsioPrivate> ts = boost::dynamic_pointer_cast<TransportServerAsioPrivate>(p);
    ts->onAccept(erc, s);
  }

  void TransportServerAsioPrivate::onAccept(const boost::system::error_code& erc,
#ifdef WITH_SSL
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket>* s
#else
    boost::asio::ip::tcp::socket* s
#endif
    )
  {
    qiLogDebug() << this << " onAccept";
    if (!_live)
    {
      delete s;
      return;
    }
    if (erc)
    {
      qiLogDebug() << "accept error " << erc.message();
      delete s;
      self->acceptError(erc.value());
      delete _acceptor;
      _acceptor = 0;
      return;
    }
    qi::TransportSocketPtr socket = qi::TcpTransportSocketPtr(new TcpTransportSocket(context, _ssl, s));
    self->newConnection(socket);

    if (socket.unique()) {
      qiLogError() << "bug: socket not stored by the newConnection handler (usecount:" << socket.use_count() << ")";
    }
#ifdef WITH_SSL
    _s = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(_acceptor->get_io_service(), _sslContext);
#else
    _s = new boost::asio::ip::tcp::socket(_acceptor->get_io_service());
#endif
    _acceptor->async_accept(_s->lowest_layer(),
                           boost::bind(_onAccept, shared_from_this(), _1, _s));
  }

  void TransportServerAsioPrivate::close() {
    qiLogDebug() << this << " close";
    try
    {
      _asyncEndpoints.cancel();
    }
    catch (const std::runtime_error& e)
    {
      qiLogDebug() << e.what();
    }

    _live = false;
    if (_acceptor)
      _acceptor->close();
  }

  /*
   * This asynchronous call will keep a shared ptr on the object to prevent
   * its destruction.
   */
  void _updateEndpoints(TransportServerImplPtr p)
  {
    boost::shared_ptr<TransportServerAsioPrivate> ts = boost::dynamic_pointer_cast<TransportServerAsioPrivate>(p);
    ts->updateEndpoints();
  }

  /*
   * This function is used to detect and update endpoints when the transport
   * server is listening on 0.0.0.0.
   */
  void TransportServerAsioPrivate::updateEndpoints()
  {
    if (!_live)
    {
      return;
    }

    // TODO: implement OS networking notifications

    qiLogDebug() << "Checking endpoints...";
    std::vector<qi::Url> currentEndpoints;

    std::map<std::string, std::vector<std::string> > ifsMap = qi::os::hostIPAddrs();
    if (ifsMap.empty())
    {
      const char* s = "Cannot get host addresses";
      qiLogWarning() << s;
    }

    std::string protocol = _ssl ? "tcps://" : "tcp://";

    {
      for (std::map<std::string, std::vector<std::string> >::iterator interfaceIt = ifsMap.begin();
           interfaceIt != ifsMap.end();
           ++interfaceIt)
      {
        for (std::vector<std::string>::iterator addressIt = (*interfaceIt).second.begin();
             addressIt != (*interfaceIt).second.end();
             ++addressIt)
        {
          std::stringstream ss;
          ss << protocol << (*addressIt) << ":" << _port;
          currentEndpoints.push_back(ss.str());
        }
      }
    }

    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      if (_endpoints.size() != currentEndpoints.size() ||
          !std::equal(_endpoints.begin(), _endpoints.end(), currentEndpoints.begin()))
      {
        std::stringstream ss;
        std::vector<qi::Url>::iterator it;
        for (it = currentEndpoints.begin(); it != currentEndpoints.end(); ++it)
          ss << "ep: " << it->str() << std::endl;
        qiLogVerbose() << "Updating endpoints..." << this << std::endl << ss.str();
        _endpoints = currentEndpoints;
        _self->endpointsChanged();
      }

    }

    _asyncEndpoints = context->async(boost::bind(_updateEndpoints, shared_from_this()),
                                     ifsMonitoringTimeout);
  }

  qi::Future<void> TransportServerAsioPrivate::listen(const qi::Url& url)
  {
    qi::Url listenUrl = url;
    _ssl = listenUrl.protocol() == "tcps";
    using namespace boost::asio;
#ifndef ANDROID
    // resolve endpoint
    ip::tcp::resolver r(_acceptor->get_io_service());
    ip::tcp::resolver::query q(listenUrl.host(), boost::lexical_cast<std::string>(listenUrl.port()),
                               boost::asio::ip::tcp::resolver::query::all_matching);
    ip::tcp::resolver::iterator it = r.resolve(q);
    if (it == ip::tcp::resolver::iterator())
    {
      const char* s = "Listen error: no endpoint.";
      qiLogError() << s;
      return qi::makeFutureError<void>(s);
    }
    ip::tcp::endpoint ep = *it;
#else
    ip::tcp::endpoint ep(boost::asio::ip::address::from_string(url.host()), url.port());
#endif // #ifndef ANDROID

    qiLogDebug() << "Will listen on " << ep.address().to_string() << ' ' << ep.port();
    _acceptor->open(ep.protocol());
#ifdef _WIN32
    boost::asio::socket_base::reuse_address option(false);
#else
    boost::asio::socket_base::reuse_address option(true);
    fcntl(_acceptor->native(), F_SETFD, FD_CLOEXEC);
#endif
    _acceptor->set_option(option);
    _acceptor->bind(ep);
    boost::system::error_code ec;
    _acceptor->listen(socket_base::max_connections, ec);
    if (ec)
    {
      qiLogError("qimessaging.server.listen") << ec.message();
      return qi::makeFutureError<void>(ec.message());
    }
    _port = _acceptor->local_endpoint().port();// already in host byte orde
    qiLogDebug() << "Effective port io_service" << _port;
    if (listenUrl.port() == 0)
    {
      listenUrl = Url(listenUrl.protocol() + "://" + listenUrl.host() + ":"
        + boost::lexical_cast<std::string>(_port));
    }

    /* Set endpoints */
    if (listenUrl.host() != "0.0.0.0")
    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      _endpoints.push_back(listenUrl.str());
    }
    else
    {
      updateEndpoints();
    }

    {
      boost::mutex::scoped_lock l(_endpointsMutex);
      for (std::vector<qi::Url>::const_iterator it = _endpoints.begin();
           it != _endpoints.end();
           it++)
      {
        qiLogInfo() << "TransportServer will listen on: " << it->str();
      }
    }

#ifdef WITH_SSL
    if (_ssl)
    {
      if (self->_identityCertificate.empty() || self->_identityKey.empty())
      {
        const char* s = "SSL certificates missing, please call Session::setIdentity first";
        qiLogError("qimessaging.server.listen") << s;
        return qi::makeFutureError<void>(s);
      }

      _sslContext.set_options(
        boost::asio::ssl::context::default_workarounds
        | boost::asio::ssl::context::no_sslv2);
      _sslContext.use_certificate_chain_file(self->_identityCertificate.c_str());
      _sslContext.use_private_key_file(self->_identityKey.c_str(), boost::asio::ssl::context::pem);
    }

    _s = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(_acceptor->get_io_service(), _sslContext);
#else
    _s = new boost::asio::ip::tcp::socket(_acceptor->get_io_service());
#endif
    _acceptor->async_accept(_s->lowest_layer(),
      boost::bind(_onAccept, shared_from_this(), _1, _s));
    _connectionPromise.setValue(0);
    return _connectionPromise.future();
  }

  TransportServerAsioPrivate::TransportServerAsioPrivate(TransportServer* self,
                                                                 EventLoop* ctx)
    : TransportServerImpl(self, ctx)
    , _self(self)
    , _acceptor(new boost::asio::ip::tcp::acceptor(*(boost::asio::io_service*)ctx->nativeHandle()))
    , _live(true)
#ifdef WITH_SSL
    , _sslContext(*(boost::asio::io_service*)ctx->nativeHandle(), boost::asio::ssl::context::sslv23)
#endif
    , _ssl(false)
  {
  }

  TransportServerAsioPrivate::~TransportServerAsioPrivate()
  {
    delete _acceptor;
    _acceptor = 0;
  }
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persons-presence-model.h"
#include "persons-model.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>

#include <KTp/contact-factory.h>
#include <KTp/global-contact-manager.h>
#include <KDebug>

PersonsPresenceModel::PersonsPresenceModel(QObject *parent)
: QIdentityProxyModel(parent)
{
    Tp::AccountFactoryPtr  accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(),
                                                                       Tp::Features() << Tp::Account::FeatureCore
                                                                       << Tp::Account::FeatureCapabilities
                                                                       << Tp::Account::FeatureProtocolInfo
                                                                       << Tp::Account::FeatureProfile);

    Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
                                                                               Tp::Features() << Tp::Connection::FeatureCore
                                                                               << Tp::Connection::FeatureRoster
                                                                               << Tp::Connection::FeatureSelfContact);

    Tp::ContactFactoryPtr contactFactory = KTp::ContactFactory::create(Tp::Features()  << Tp::Contact::FeatureAlias
                                                                        << Tp::Contact::FeatureSimplePresence
                                                                        << Tp::Contact::FeatureCapabilities
                                                                        << Tp::Contact::FeatureClientTypes);

    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());

    m_accountManager = Tp::AccountManager::create(QDBusConnection::sessionBus(),
                                                  accountFactory,
                                                  connectionFactory,
                                                  channelFactory,
                                                  contactFactory);

    connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
            this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));
}

PersonsPresenceModel::~PersonsPresenceModel()
{

}

void PersonsPresenceModel::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Failed to initialize AccountManager:" << op->errorName();
        kWarning() << op->errorMessage();

        return;
    }

    kDebug() << "Account manager ready";

    m_contactManager = new KTp::GlobalContactManager(m_accountManager, this);
    connect(m_contactManager, SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(m_contactManager->allKnownContacts(), Tp::Contacts());
}

void PersonsPresenceModel::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &contact, contactsRemoved) {
            m_contacts.remove(contact->id());
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        Tp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        m_contacts.insert(contact->id(), ktpContact);

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactChanged()));

        //TODO: add other stuff here etc

        QModelIndex index = qobject_cast<PersonsModel*>(sourceModel())->findRecursively(PersonsModel::IMRole, contact->id());
        Q_EMIT dataChanged(index, index);
        if (index.parent().isValid()) {
            Q_EMIT dataChanged(index.parent(), index.parent());
        }
    }
}

void PersonsPresenceModel::onContactChanged()
{
    QString id = qobject_cast<Tp::Contact*>(sender())->id();

    QModelIndex index = qobject_cast<PersonsModel*>(sourceModel())->findRecursively(PersonsModel::IMRole, id);
    Q_EMIT dataChanged(index, index);
}

QVariant PersonsPresenceModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    if (role == PersonsModel::StatusRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return m_presences.value(contactId)->presence().status();
            } else if (!contactId.isEmpty()) {
                return QLatin1String("offline");
            } else if (contactId.isEmpty()) {
                return QLatin1String("unknown");
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    } else if (role == PersonsModel::IMAccountRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return QVariant::fromValue<Tp::AccountPtr>(m_contactManager->accountForContact(m_presences.value(contactId)));
            } else {
                return QVariant();
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    } else if (role == PersonsModel::IMContactRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return QVariant::fromValue<Tp::ContactPtr>(m_presences.value(contactId));
            } else {
                return QVariant();
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    }

    return QIdentityProxyModel::data(index, role);
}

QVariantList PersonsPresenceModel::queryChildrenForData(const QModelIndex &index, int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = index.child(i, 0).data(role);
        if (!value.isNull()) {
            ret += value;
        }
    }

    return ret;
}
<commit_msg>Emit dataChanged() also when the contacts get removed<commit_after>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persons-presence-model.h"
#include "persons-model.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>

#include <KTp/contact-factory.h>
#include <KTp/global-contact-manager.h>
#include <KDebug>

PersonsPresenceModel::PersonsPresenceModel(QObject *parent)
: QIdentityProxyModel(parent)
{
    Tp::AccountFactoryPtr  accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(),
                                                                       Tp::Features() << Tp::Account::FeatureCore
                                                                       << Tp::Account::FeatureCapabilities
                                                                       << Tp::Account::FeatureProtocolInfo
                                                                       << Tp::Account::FeatureProfile);

    Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
                                                                               Tp::Features() << Tp::Connection::FeatureCore
                                                                               << Tp::Connection::FeatureRoster
                                                                               << Tp::Connection::FeatureSelfContact);

    Tp::ContactFactoryPtr contactFactory = KTp::ContactFactory::create(Tp::Features()  << Tp::Contact::FeatureAlias
                                                                        << Tp::Contact::FeatureSimplePresence
                                                                        << Tp::Contact::FeatureCapabilities
                                                                        << Tp::Contact::FeatureClientTypes);

    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());

    m_accountManager = Tp::AccountManager::create(QDBusConnection::sessionBus(),
                                                  accountFactory,
                                                  connectionFactory,
                                                  channelFactory,
                                                  contactFactory);

    connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
            this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));
}

PersonsPresenceModel::~PersonsPresenceModel()
{

}

void PersonsPresenceModel::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Failed to initialize AccountManager:" << op->errorName();
        kWarning() << op->errorMessage();

        return;
    }

    kDebug() << "Account manager ready";

    m_contactManager = new KTp::GlobalContactManager(m_accountManager, this);
    connect(m_contactManager, SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(m_contactManager->allKnownContacts(), Tp::Contacts());
}

void PersonsPresenceModel::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &contact, contactsRemoved) {
            m_contacts.remove(contact->id());

            QModelIndex index = qobject_cast<PersonsModel*>(sourceModel())->findRecursively(PersonsModel::IMRole, contact->id());
            Q_EMIT dataChanged(index, index);
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        Tp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        m_contacts.insert(contact->id(), ktpContact);

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactChanged()));

        //TODO: add other stuff here etc

        QModelIndex index = qobject_cast<PersonsModel*>(sourceModel())->findRecursively(PersonsModel::IMRole, contact->id());
        Q_EMIT dataChanged(index, index);
        if (index.parent().isValid()) {
            Q_EMIT dataChanged(index.parent(), index.parent());
        }
    }
}

void PersonsPresenceModel::onContactChanged()
{
    QString id = qobject_cast<Tp::Contact*>(sender())->id();

    QModelIndex index = qobject_cast<PersonsModel*>(sourceModel())->findRecursively(PersonsModel::IMRole, id);
    Q_EMIT dataChanged(index, index);
}

QVariant PersonsPresenceModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    if (role == PersonsModel::StatusRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return m_presences.value(contactId)->presence().status();
            } else if (!contactId.isEmpty()) {
                return QLatin1String("offline");
            } else if (contactId.isEmpty()) {
                return QLatin1String("unknown");
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    } else if (role == PersonsModel::IMAccountRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return QVariant::fromValue<Tp::AccountPtr>(m_contactManager->accountForContact(m_presences.value(contactId)));
            } else {
                return QVariant();
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    } else if (role == PersonsModel::IMContactRole) {
        if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Contact) {
            QString contactId = index.data(PersonsModel::IMRole).toString();
            if (m_presences.keys().contains(contactId)) {
                return QVariant::fromValue<Tp::ContactPtr>(m_presences.value(contactId));
            } else {
                return QVariant();
            }
        } else if (index.data(PersonsModel::ResourceTypeRole).toUInt() == PersonsModel::Person) {
            return queryChildrenForData(index, role);
        }
    }

    return QIdentityProxyModel::data(index, role);
}

QVariantList PersonsPresenceModel::queryChildrenForData(const QModelIndex &index, int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = index.child(i, 0).data(role);
        if (!value.isNull()) {
            ret += value;
        }
    }

    return ret;
}
<|endoftext|>


<commit_before>#include "query_result_widget.hh"

using namespace GSQLiteui;

QueryResultsWidget::QueryResultsWidget(statement_t&& s)
    : Glib::ObjectBase("gsqliteui_QueryResultsWidget")
    , Gtk::TreeView()
    , statement(std::move(s))
{
    auto cols = this->statement->columns();
    for(int i = 0; i < cols; i += 1) {
        Gtk::TreeModelColumn<Glib::ustring> col;
        this->columns.add(col);
        this->append_column(this->statement->origin_name(i), col);
    }

    this->store = Gtk::ListStore::create(this->columns);
    this->set_model(this->store);
    this->set_headers_visible(true);

    /// TODO:
    /// 1. Cancel on destruction
    /// 2. Don't fill everything at once, instead do so as the user scrolls
    /// …?
    /// 4. Restrict the size of fields and ellipsize
    /// 5. When row is selected expand and show full contents (?)
    /// 6. Consider how to display the NULL columns (grayed out would be nice?)
    /// 7. Lots more…
    this->statement->iterate([this, cols](Statement::result_t row){
        if(row->state().get_value() == Row::DONE) return false;
        auto iter = this->store->append();
        for(int i = 0; i < cols; i += 1){
            auto val = (*row)[i];
            if(val == nullptr) return true;
            switch(val->getType()){
                case SQLITE_TEXT:
                    iter->set_value(i, Glib::ustring(
                        reinterpret_cast<const char *>(
                            **dynamic_cast<TextValue*>(val)
                        )
                    ));
                    break;
                default:
                    iter->set_value(i, Glib::ustring("<not implemented>"));
                    break;
            }
        }
        return true;
    });
}

QueryResultsWidget::~QueryResultsWidget(){
}
<commit_msg>Implement other data types<commit_after>#include "query_result_widget.hh"

using namespace GSQLiteui;

QueryResultsWidget::QueryResultsWidget(statement_t&& s)
    : Glib::ObjectBase("gsqliteui_QueryResultsWidget")
    , Gtk::TreeView()
    , statement(std::move(s))
{
    auto cols = this->statement->columns();
    for(int i = 0; i < cols; i += 1) {
        Gtk::TreeModelColumn<Glib::ustring> col;
        this->columns.add(col);
        this->append_column(this->statement->origin_name(i), col);
    }

    this->store = Gtk::ListStore::create(this->columns);
    this->set_model(this->store);
    this->set_headers_visible(true);

    /// TODO:
    /// 1. Cancel on destruction
    /// 2. Don't fill everything at once, instead do so as the user scrolls
    /// …?
    /// 4. Restrict the size of fields and ellipsize
    /// 5. When row is selected expand and show full contents (?)
    /// 6. Consider how to display the NULL columns (grayed out would be nice?)
    /// 7. Lots more…
    this->statement->iterate([this, cols](Statement::result_t row){
        if(row->state().get_value() == Row::DONE) return false;
        auto iter = this->store->append();
        for(int i = 0; i < cols; i += 1){
            auto val = (*row)[i];
            if(val == nullptr) return true;
            switch(val->getType()){
                case SQLITE_TEXT:
                    iter->set_value(i, Glib::ustring(
                        reinterpret_cast<const char *>(
                            **dynamic_cast<TextValue*>(val)
                        )
                    ));
                    break;
                case SQLITE_INTEGER:
                    iter->set_value(i, Glib::ustring(std::to_string(
                        **dynamic_cast<IntValue*>(val)
                    )));
                    break;
                case SQLITE_FLOAT:
                    iter->set_value(i, Glib::ustring(std::to_string(
                        **dynamic_cast<FloatValue*>(val)
                    )));
                    break;
                case SQLITE_BLOB:
                    iter->set_value(i, Glib::ustring("<Blob: not implemented>"));
                    break;
            }
        }
        return true;
    });
}

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