<commit_before>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/filesystem/operations.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionPlugin.hpp>

#ifdef PION_WIN32
	#include <windows.h>
#else
	#include <dlfcn.h>
#endif

namespace pion {	// begin namespace pion

// static members of PionPlugin

const std::string			PionPlugin::PION_PLUGIN_CREATE("pion_create_");
const std::string			PionPlugin::PION_PLUGIN_DESTROY("pion_destroy_");
#ifdef PION_WIN32
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".dll");
#else
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".so");
#endif
const std::string			PionPlugin::PION_CONFIG_EXTENSION(".conf");
std::vector<std::string>	PionPlugin::m_plugin_dirs;
PionPlugin::PluginMap		PionPlugin::m_plugin_map;
boost::mutex				PionPlugin::m_plugin_mutex;
PionPlugin::StaticEntryPointList	*PionPlugin::m_entry_points_ptr = NULL;

// PionPlugin member functions

void PionPlugin::checkCygwinPath(boost::filesystem::path& final_path,
								 const std::string& start_path)
{
#if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
	// try prepending PION_CYGWIN_DIRECTORY if not complete
	if (! final_path.is_complete() && final_path.has_root_directory()) {
		final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
	}
#endif
}

void PionPlugin::addPluginDirectory(const std::string& dir)
{
	boost::filesystem::path plugin_path = boost::filesystem::system_complete(dir);
	checkCygwinPath(plugin_path, dir);
	if (! boost::filesystem::exists(plugin_path) )
		throw DirectoryNotFoundException(dir);
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.push_back(plugin_path.directory_string());
}

void PionPlugin::resetPluginDirectories(void)
{
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.clear();
}

void PionPlugin::open(const std::string& plugin_name)
{
	std::string plugin_file;

	if (!findPluginFile(plugin_file, plugin_name))
		throw PluginNotFoundException(plugin_name);

	openFile(plugin_file);
}

void PionPlugin::openFile(const std::string& plugin_file)
{
	releaseData();	// make sure we're not already pointing to something

	// use a temporary object first since openPlugin() may throw
	PionPluginData plugin_data(getPluginName(plugin_file));

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_data.m_plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// open up the shared library using our temporary data object
		openPlugin(plugin_file, plugin_data);	// may throw

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_data);
		m_plugin_map.insert( std::make_pair(m_plugin_data->m_plugin_name,
											m_plugin_data) );
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::openStaticLinked(const std::string& plugin_name,
								  void *create_func,
								  void *destroy_func)
{
	releaseData();	// make sure we're not already pointing to something

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_name);
		m_plugin_data->m_lib_handle = NULL; // this will indicate that we are using statically linked plug-in
		m_plugin_data->m_create_func = create_func;
		m_plugin_data->m_destroy_func = destroy_func;
		m_plugin_map.insert(std::make_pair(m_plugin_data->m_plugin_name,
										   m_plugin_data));
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::releaseData(void)
{
	if (m_plugin_data != NULL) {
		boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
		// double-check after locking mutex
		if (m_plugin_data != NULL && --m_plugin_data->m_references == 0) {
			// no more references to the plug-in library

			// release the shared object
			closeDynamicLibrary(m_plugin_data->m_lib_handle);

			// remove it from the plug-in map
			PluginMap::iterator itr = m_plugin_map.find(m_plugin_data->m_plugin_name);
			// check itr just to be safe (it SHOULD always find a match)
			if (itr != m_plugin_map.end())
				m_plugin_map.erase(itr);

			// release the heap object
			delete m_plugin_data;
		}
		m_plugin_data = NULL;
	}
}

void PionPlugin::grabData(const PionPlugin& p)
{
	releaseData();	// make sure we're not already pointing to something
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_data = const_cast<PionPluginData*>(p.m_plugin_data);
	if (m_plugin_data != NULL) {
		++ m_plugin_data->m_references;
	}
}

bool PionPlugin::findFile(std::string& path_to_file, const std::string& name,
						  const std::string& extension)
{
	// first, try the name as-is
	if (checkForFile(path_to_file, name, "", extension))
		return true;

	// nope, check search paths
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	for (std::vector<std::string>::iterator i = m_plugin_dirs.begin();
		 i != m_plugin_dirs.end(); ++i)
	{
		if (checkForFile(path_to_file, *i, name, extension))
			return true;
	}

	// no plug-in file found
	return false;
}

bool PionPlugin::checkForFile(std::string& final_path, const std::string& start_path,
							  const std::string& name, const std::string& extension)
{
	// check for cygwin path oddities
	boost::filesystem::path cygwin_safe_path(start_path);
	checkCygwinPath(cygwin_safe_path, start_path);
	boost::filesystem::path test_path(cygwin_safe_path);

	// if a name is specified, append it to the test path
	if (! name.empty())
		test_path /= name;

	// check for existence of plug-in (without extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// next, try appending the plug-in extension
	if (name.empty()) {
		// no "name" specified -> append it directly to start_path
		test_path = boost::filesystem::path(start_path + extension);
		// in this case, we need to re-check for the cygwin oddities
		checkCygwinPath(test_path, start_path + extension);
	} else {
		// name is specified, so we can just re-use cygwin_safe_path
		test_path = cygwin_safe_path /
			boost::filesystem::path(name + extension);
	}

	// re-check for existence of plug-in (after adding extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// no plug-in file found
	return false;
}

void PionPlugin::openPlugin(const std::string& plugin_file,
							PionPluginData& plugin_data)
{
	// get the name of the plugin (for create/destroy symbol names)
	plugin_data.m_plugin_name = getPluginName(plugin_file);

	// attempt to open the plugin; note that this tries all search paths
	// and also tries a variety of platform-specific extensions
	plugin_data.m_lib_handle = loadDynamicLibrary(plugin_file.c_str());
	if (plugin_data.m_lib_handle == NULL)
		throw PluginNotFoundException(plugin_file);

	// find the function used to create new plugin objects
	plugin_data.m_create_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
	if (plugin_data.m_create_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingCreateException(plugin_file);
	}

	// find the function used to destroy existing plugin objects
	plugin_data.m_destroy_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
	if (plugin_data.m_destroy_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingDestroyException(plugin_file);
	}
}

std::string PionPlugin::getPluginName(const std::string& plugin_file)
{
	// strip path
#ifdef PION_WIN32
	std::string::size_type pos = plugin_file.find_last_of("\\/");
#else
	std::string::size_type pos = plugin_file.find_last_of('/');
#endif
	std::string plugin_name = (pos == std::string::npos ?
							   plugin_file : plugin_file.substr(pos+1));
	pos = plugin_name.find('.');

	// truncate extension
	if (pos != std::string::npos)
		plugin_name.resize(pos);

	return plugin_name;
}

void *PionPlugin::loadDynamicLibrary(const std::string& plugin_file)
{
#ifdef PION_WIN32
	#ifdef _MSC_VER
		return LoadLibraryA(plugin_file.c_str());
	#else
		return LoadLibrary(plugin_file.c_str());
	#endif
#else
	return dlopen(plugin_file.c_str(), RTLD_LAZY);
#endif
}

void PionPlugin::closeDynamicLibrary(void *lib_handle)
{
#ifdef PION_WIN32
	FreeLibrary((HINSTANCE) lib_handle);
#else
	dlclose(lib_handle);
#endif
}

void *PionPlugin::getLibrarySymbol(void *lib_handle, const std::string& symbol)
{
#ifdef PION_WIN32
	return (void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
#else
	return dlsym(lib_handle, symbol.c_str());
#endif
}

bool PionPlugin::findStaticEntryPoint(const std::string& plugin_name,
									  void **create_func,
									  void **destroy_func)
{
	// check simple case first: no entry points exist
	if (m_entry_points_ptr == NULL || m_entry_points_ptr->empty())
		return false;

	// try to find the entry point for the plugin
	for (std::list<StaticEntryPoint>::const_iterator i = m_entry_points_ptr->begin();
		 i != m_entry_points_ptr->end(); ++i) {
			if (i->m_plugin_name==plugin_name) {
				*create_func  = i->m_create_func;
				*destroy_func = i->m_destroy_func;
				return true;
			}
	}
	return false;
}

void PionPlugin::addStaticEntryPoint(const std::string& plugin_name,
									 void *create_func,
									 void *destroy_func)
{
	// make sure that this function can only be called by one thread at a time
	static boost::mutex			entrypoint_mutex;
	boost::mutex::scoped_lock	entrypoint_lock(entrypoint_mutex);

	// create the entry point list if it doesn't already exist
	if (m_entry_points_ptr == NULL)
		m_entry_points_ptr = new StaticEntryPointList;

	// insert it into the entry point list
	m_entry_points_ptr->push_back(StaticEntryPoint(plugin_name, create_func, destroy_func));
}

}	// end namespace pion
<commit_msg>Simplified PionPlugin::getPluginName.<commit_after>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/filesystem.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionPlugin.hpp>

#ifdef PION_WIN32
	#include <windows.h>
#else
	#include <dlfcn.h>
#endif

namespace pion {	// begin namespace pion

// static members of PionPlugin

const std::string			PionPlugin::PION_PLUGIN_CREATE("pion_create_");
const std::string			PionPlugin::PION_PLUGIN_DESTROY("pion_destroy_");
#ifdef PION_WIN32
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".dll");
#else
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".so");
#endif
const std::string			PionPlugin::PION_CONFIG_EXTENSION(".conf");
std::vector<std::string>	PionPlugin::m_plugin_dirs;
PionPlugin::PluginMap		PionPlugin::m_plugin_map;
boost::mutex				PionPlugin::m_plugin_mutex;
PionPlugin::StaticEntryPointList	*PionPlugin::m_entry_points_ptr = NULL;

// PionPlugin member functions

void PionPlugin::checkCygwinPath(boost::filesystem::path& final_path,
								 const std::string& start_path)
{
#if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
	// try prepending PION_CYGWIN_DIRECTORY if not complete
	if (! final_path.is_complete() && final_path.has_root_directory()) {
		final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
	}
#endif
}

void PionPlugin::addPluginDirectory(const std::string& dir)
{
	boost::filesystem::path plugin_path = boost::filesystem::system_complete(dir);
	checkCygwinPath(plugin_path, dir);
	if (! boost::filesystem::exists(plugin_path) )
		throw DirectoryNotFoundException(dir);
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.push_back(plugin_path.directory_string());
}

void PionPlugin::resetPluginDirectories(void)
{
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.clear();
}

void PionPlugin::open(const std::string& plugin_name)
{
	std::string plugin_file;

	if (!findPluginFile(plugin_file, plugin_name))
		throw PluginNotFoundException(plugin_name);

	openFile(plugin_file);
}

void PionPlugin::openFile(const std::string& plugin_file)
{
	releaseData();	// make sure we're not already pointing to something

	// use a temporary object first since openPlugin() may throw
	PionPluginData plugin_data(getPluginName(plugin_file));

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_data.m_plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// open up the shared library using our temporary data object
		openPlugin(plugin_file, plugin_data);	// may throw

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_data);
		m_plugin_map.insert( std::make_pair(m_plugin_data->m_plugin_name,
											m_plugin_data) );
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::openStaticLinked(const std::string& plugin_name,
								  void *create_func,
								  void *destroy_func)
{
	releaseData();	// make sure we're not already pointing to something

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_name);
		m_plugin_data->m_lib_handle = NULL; // this will indicate that we are using statically linked plug-in
		m_plugin_data->m_create_func = create_func;
		m_plugin_data->m_destroy_func = destroy_func;
		m_plugin_map.insert(std::make_pair(m_plugin_data->m_plugin_name,
										   m_plugin_data));
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::releaseData(void)
{
	if (m_plugin_data != NULL) {
		boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
		// double-check after locking mutex
		if (m_plugin_data != NULL && --m_plugin_data->m_references == 0) {
			// no more references to the plug-in library

			// release the shared object
			closeDynamicLibrary(m_plugin_data->m_lib_handle);

			// remove it from the plug-in map
			PluginMap::iterator itr = m_plugin_map.find(m_plugin_data->m_plugin_name);
			// check itr just to be safe (it SHOULD always find a match)
			if (itr != m_plugin_map.end())
				m_plugin_map.erase(itr);

			// release the heap object
			delete m_plugin_data;
		}
		m_plugin_data = NULL;
	}
}

void PionPlugin::grabData(const PionPlugin& p)
{
	releaseData();	// make sure we're not already pointing to something
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_data = const_cast<PionPluginData*>(p.m_plugin_data);
	if (m_plugin_data != NULL) {
		++ m_plugin_data->m_references;
	}
}

bool PionPlugin::findFile(std::string& path_to_file, const std::string& name,
						  const std::string& extension)
{
	// first, try the name as-is
	if (checkForFile(path_to_file, name, "", extension))
		return true;

	// nope, check search paths
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	for (std::vector<std::string>::iterator i = m_plugin_dirs.begin();
		 i != m_plugin_dirs.end(); ++i)
	{
		if (checkForFile(path_to_file, *i, name, extension))
			return true;
	}

	// no plug-in file found
	return false;
}

bool PionPlugin::checkForFile(std::string& final_path, const std::string& start_path,
							  const std::string& name, const std::string& extension)
{
	// check for cygwin path oddities
	boost::filesystem::path cygwin_safe_path(start_path);
	checkCygwinPath(cygwin_safe_path, start_path);
	boost::filesystem::path test_path(cygwin_safe_path);

	// if a name is specified, append it to the test path
	if (! name.empty())
		test_path /= name;

	// check for existence of plug-in (without extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// next, try appending the plug-in extension
	if (name.empty()) {
		// no "name" specified -> append it directly to start_path
		test_path = boost::filesystem::path(start_path + extension);
		// in this case, we need to re-check for the cygwin oddities
		checkCygwinPath(test_path, start_path + extension);
	} else {
		// name is specified, so we can just re-use cygwin_safe_path
		test_path = cygwin_safe_path /
			boost::filesystem::path(name + extension);
	}

	// re-check for existence of plug-in (after adding extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// no plug-in file found
	return false;
}

void PionPlugin::openPlugin(const std::string& plugin_file,
							PionPluginData& plugin_data)
{
	// get the name of the plugin (for create/destroy symbol names)
	plugin_data.m_plugin_name = getPluginName(plugin_file);

	// attempt to open the plugin; note that this tries all search paths
	// and also tries a variety of platform-specific extensions
	plugin_data.m_lib_handle = loadDynamicLibrary(plugin_file.c_str());
	if (plugin_data.m_lib_handle == NULL)
		throw PluginNotFoundException(plugin_file);

	// find the function used to create new plugin objects
	plugin_data.m_create_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
	if (plugin_data.m_create_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingCreateException(plugin_file);
	}

	// find the function used to destroy existing plugin objects
	plugin_data.m_destroy_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
	if (plugin_data.m_destroy_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingDestroyException(plugin_file);
	}
}

std::string PionPlugin::getPluginName(const std::string& plugin_file)
{
	return boost::filesystem::basename(boost::filesystem::path(plugin_file));
}

void *PionPlugin::loadDynamicLibrary(const std::string& plugin_file)
{
#ifdef PION_WIN32
	#ifdef _MSC_VER
		return LoadLibraryA(plugin_file.c_str());
	#else
		return LoadLibrary(plugin_file.c_str());
	#endif
#else
	return dlopen(plugin_file.c_str(), RTLD_LAZY);
#endif
}

void PionPlugin::closeDynamicLibrary(void *lib_handle)
{
#ifdef PION_WIN32
	FreeLibrary((HINSTANCE) lib_handle);
#else
	dlclose(lib_handle);
#endif
}

void *PionPlugin::getLibrarySymbol(void *lib_handle, const std::string& symbol)
{
#ifdef PION_WIN32
	return (void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
#else
	return dlsym(lib_handle, symbol.c_str());
#endif
}

bool PionPlugin::findStaticEntryPoint(const std::string& plugin_name,
									  void **create_func,
									  void **destroy_func)
{
	// check simple case first: no entry points exist
	if (m_entry_points_ptr == NULL || m_entry_points_ptr->empty())
		return false;

	// try to find the entry point for the plugin
	for (std::list<StaticEntryPoint>::const_iterator i = m_entry_points_ptr->begin();
		 i != m_entry_points_ptr->end(); ++i) {
			if (i->m_plugin_name==plugin_name) {
				*create_func  = i->m_create_func;
				*destroy_func = i->m_destroy_func;
				return true;
			}
	}
	return false;
}

void PionPlugin::addStaticEntryPoint(const std::string& plugin_name,
									 void *create_func,
									 void *destroy_func)
{
	// make sure that this function can only be called by one thread at a time
	static boost::mutex			entrypoint_mutex;
	boost::mutex::scoped_lock	entrypoint_lock(entrypoint_mutex);

	// create the entry point list if it doesn't already exist
	if (m_entry_points_ptr == NULL)
		m_entry_points_ptr = new StaticEntryPointList;

	// insert it into the entry point list
	m_entry_points_ptr->push_back(StaticEntryPoint(plugin_name, create_func, destroy_func));
}

}	// end namespace pion
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Intel Corporation
 *
 * 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 HAVE_CONFIG_H
#include "config.h"
#endif

// primary header
#include "utils.h"

// library headers
#include "common/unittest.h"
#include "common/common_def.h"

// system headers
#include <limits>
#include <sstream>
#include <va/va.h>

#define UTILS_TEST(name) \
    TEST(UtilsTest, name)

using namespace YamiMediaCodec;

UTILS_TEST(guessFourcc) {
    EXPECT_EQ(guessFourcc("test.i420"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test.nv12"), (uint32_t)YAMI_FOURCC_NV12);
    EXPECT_EQ(guessFourcc("test.yv12"), (uint32_t)YAMI_FOURCC_YV12);
    EXPECT_EQ(guessFourcc("test.yuy2"), (uint32_t)YAMI_FOURCC_YUY2);
    EXPECT_EQ(guessFourcc("test.uyvy"), (uint32_t)YAMI_FOURCC_UYVY);
    EXPECT_EQ(guessFourcc("test.rgbx"), (uint32_t)YAMI_FOURCC_RGBX);
    EXPECT_EQ(guessFourcc("test.bgrx"), (uint32_t)YAMI_FOURCC_BGRX);
    EXPECT_EQ(guessFourcc("test.xrgb"), (uint32_t)YAMI_FOURCC_XRGB);
    EXPECT_EQ(guessFourcc("test.xbgr"), (uint32_t)YAMI_FOURCC_XBGR);

    EXPECT_EQ(guessFourcc("test.txt"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test"), (uint32_t)YAMI_FOURCC_I420);

    EXPECT_EQ(guessFourcc("test.I420"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test.NV12"), (uint32_t)YAMI_FOURCC_NV12);
    EXPECT_EQ(guessFourcc("test.YV12"), (uint32_t)YAMI_FOURCC_YV12);
    EXPECT_EQ(guessFourcc("test.YUY2"), (uint32_t)YAMI_FOURCC_YUY2);
    EXPECT_EQ(guessFourcc("test.UYVY"), (uint32_t)YAMI_FOURCC_UYVY);
    EXPECT_EQ(guessFourcc("test.RGBX"), (uint32_t)YAMI_FOURCC_RGBX);
    EXPECT_EQ(guessFourcc("test.BGRX"), (uint32_t)YAMI_FOURCC_BGRX);
    EXPECT_EQ(guessFourcc("test.XRGB"), (uint32_t)YAMI_FOURCC_XRGB);
    EXPECT_EQ(guessFourcc("test.XBGR"), (uint32_t)YAMI_FOURCC_XBGR);
}

UTILS_TEST(guessResolutionBasic) {
    int w(-1), h(-1);
    EXPECT_TRUE(guessResolution("test1920x1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test1920X1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test123-1920x1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test-1920x1080-123", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test1920xx1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test1080p", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test720x", w, h));
    EXPECT_EQ(w, 720);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("1280x720", w, h));
    EXPECT_EQ(w, 1280);
    EXPECT_EQ(h, 720);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("w3840h2160", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);
}

UTILS_TEST(guessResolutionOverflow) {
    std::stringstream sstream;
    int w, h;

    w = h = std::numeric_limits<int>::max();

    // sanity check
    ASSERT_GT(std::numeric_limits<long>::max(), w);
    ASSERT_GT(std::numeric_limits<long>::max(), h);

    sstream << std::numeric_limits<long>::max()
            << "x"
            << std::numeric_limits<long>::max();

    EXPECT_FALSE(guessResolution(sstream.str().c_str(), w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    sstream.str("");
    sstream << long(std::numeric_limits<int>::max()) * 2 + 3
            << "x"
            << long(std::numeric_limits<int>::max()) * 3 + 2;

    EXPECT_FALSE(guessResolution(sstream.str().c_str(), w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);
}

struct BppEntry {
    uint32_t fourcc;
    uint32_t planes;
    float bpp;
};

const static BppEntry bppEntrys[] = {
    { YAMI_FOURCC_NV12, 2, 1.5 },
    { YAMI_FOURCC_I420, 3, 1.5 },
    { YAMI_FOURCC_YV12, 3, 1.5 },
    { YAMI_FOURCC_IMC3, 3, 1.5 },
    { YAMI_FOURCC_422H, 3, 2 },
    { YAMI_FOURCC_422V, 3, 2 },
    { YAMI_FOURCC_444P, 3, 3 },
    { YAMI_FOURCC_P010, 2, 3 },
    { YAMI_FOURCC_YUY2, 1, 2 },
    { YAMI_FOURCC_UYVY, 1, 2 },
    { YAMI_FOURCC_RGBX, 1, 4 },
    { YAMI_FOURCC_RGBA, 1, 4 },
    { YAMI_FOURCC_BGRX, 1, 4 },
    { YAMI_FOURCC_BGRA, 1, 4 },
};

//check selected unsupported format.
//we do not want check all unsupported formats, it will introduce too many dependency on libva
const static uint32_t unsupported[] = {
    0,
    YAMI_FOURCC_Y800,
    YAMI_FOURCC_411P,
    YAMI_FOURCC_ARGB,
};

UTILS_TEST(getPlaneResolution)
{

    uint32_t width = 1920;
    uint32_t height = 1080;
    uint32_t planes;
    uint32_t w[3];
    uint32_t h[3];

    for (size_t i = 0; i < N_ELEMENTS(unsupported); i++) {
        EXPECT_FALSE(getPlaneResolution(unsupported[i], 1920, 1080, w, h, planes));
        EXPECT_EQ(0u, planes);
    }
    for (size_t i = 0; i < N_ELEMENTS(bppEntrys); i++) {
        const BppEntry& e = bppEntrys[i];
        EXPECT_TRUE(getPlaneResolution(e.fourcc, width, height, w, h, planes));
        EXPECT_EQ(e.planes, planes);

        float bpp;
        uint32_t bytes = 0;
        for (uint32_t p = 0; p < planes; p++) {
            bytes += w[p] * h[p];
        }
        bpp = (float)bytes / (width * height);
        EXPECT_FLOAT_EQ(e.bpp, bpp);
    }
}
<commit_msg>common/unittest: update test for Y800 support<commit_after>/*
 * Copyright 2016 Intel Corporation
 *
 * 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 HAVE_CONFIG_H
#include "config.h"
#endif

// primary header
#include "utils.h"

// library headers
#include "common/unittest.h"
#include "common/common_def.h"

// system headers
#include <limits>
#include <sstream>
#include <va/va.h>

#define UTILS_TEST(name) \
    TEST(UtilsTest, name)

using namespace YamiMediaCodec;

UTILS_TEST(guessFourcc) {
    EXPECT_EQ(guessFourcc("test.i420"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test.nv12"), (uint32_t)YAMI_FOURCC_NV12);
    EXPECT_EQ(guessFourcc("test.yv12"), (uint32_t)YAMI_FOURCC_YV12);
    EXPECT_EQ(guessFourcc("test.yuy2"), (uint32_t)YAMI_FOURCC_YUY2);
    EXPECT_EQ(guessFourcc("test.uyvy"), (uint32_t)YAMI_FOURCC_UYVY);
    EXPECT_EQ(guessFourcc("test.rgbx"), (uint32_t)YAMI_FOURCC_RGBX);
    EXPECT_EQ(guessFourcc("test.bgrx"), (uint32_t)YAMI_FOURCC_BGRX);
    EXPECT_EQ(guessFourcc("test.xrgb"), (uint32_t)YAMI_FOURCC_XRGB);
    EXPECT_EQ(guessFourcc("test.xbgr"), (uint32_t)YAMI_FOURCC_XBGR);

    EXPECT_EQ(guessFourcc("test.txt"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test"), (uint32_t)YAMI_FOURCC_I420);

    EXPECT_EQ(guessFourcc("test.I420"), (uint32_t)YAMI_FOURCC_I420);
    EXPECT_EQ(guessFourcc("test.NV12"), (uint32_t)YAMI_FOURCC_NV12);
    EXPECT_EQ(guessFourcc("test.YV12"), (uint32_t)YAMI_FOURCC_YV12);
    EXPECT_EQ(guessFourcc("test.YUY2"), (uint32_t)YAMI_FOURCC_YUY2);
    EXPECT_EQ(guessFourcc("test.UYVY"), (uint32_t)YAMI_FOURCC_UYVY);
    EXPECT_EQ(guessFourcc("test.RGBX"), (uint32_t)YAMI_FOURCC_RGBX);
    EXPECT_EQ(guessFourcc("test.BGRX"), (uint32_t)YAMI_FOURCC_BGRX);
    EXPECT_EQ(guessFourcc("test.XRGB"), (uint32_t)YAMI_FOURCC_XRGB);
    EXPECT_EQ(guessFourcc("test.XBGR"), (uint32_t)YAMI_FOURCC_XBGR);
}

UTILS_TEST(guessResolutionBasic) {
    int w(-1), h(-1);
    EXPECT_TRUE(guessResolution("test1920x1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test1920X1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test123-1920x1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("test-1920x1080-123", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 1080);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test1920xx1080", w, h));
    EXPECT_EQ(w, 1920);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test1080p", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("test720x", w, h));
    EXPECT_EQ(w, 720);
    EXPECT_EQ(h, 0);

    w = -1, h = -1;
    EXPECT_TRUE(guessResolution("1280x720", w, h));
    EXPECT_EQ(w, 1280);
    EXPECT_EQ(h, 720);

    w = -1, h = -1;
    EXPECT_FALSE(guessResolution("w3840h2160", w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);
}

UTILS_TEST(guessResolutionOverflow) {
    std::stringstream sstream;
    int w, h;

    w = h = std::numeric_limits<int>::max();

    // sanity check
    ASSERT_GT(std::numeric_limits<long>::max(), w);
    ASSERT_GT(std::numeric_limits<long>::max(), h);

    sstream << std::numeric_limits<long>::max()
            << "x"
            << std::numeric_limits<long>::max();

    EXPECT_FALSE(guessResolution(sstream.str().c_str(), w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);

    sstream.str("");
    sstream << long(std::numeric_limits<int>::max()) * 2 + 3
            << "x"
            << long(std::numeric_limits<int>::max()) * 3 + 2;

    EXPECT_FALSE(guessResolution(sstream.str().c_str(), w, h));
    EXPECT_EQ(w, 0);
    EXPECT_EQ(h, 0);
}

struct BppEntry {
    uint32_t fourcc;
    uint32_t planes;
    float bpp;
};

const static BppEntry bppEntrys[] = {
    { YAMI_FOURCC_NV12, 2, 1.5 },
    { YAMI_FOURCC_I420, 3, 1.5 },
    { YAMI_FOURCC_YV12, 3, 1.5 },
    { YAMI_FOURCC_IMC3, 3, 1.5 },
    { YAMI_FOURCC_422H, 3, 2 },
    { YAMI_FOURCC_422V, 3, 2 },
    { YAMI_FOURCC_444P, 3, 3 },
    { YAMI_FOURCC_Y800, 1, 1 },
    { YAMI_FOURCC_P010, 2, 3 },
    { YAMI_FOURCC_YUY2, 1, 2 },
    { YAMI_FOURCC_UYVY, 1, 2 },
    { YAMI_FOURCC_RGBX, 1, 4 },
    { YAMI_FOURCC_RGBA, 1, 4 },
    { YAMI_FOURCC_BGRX, 1, 4 },
    { YAMI_FOURCC_BGRA, 1, 4 },
};

//check selected unsupported format.
//we do not want check all unsupported formats, it will introduce too many dependency on libva
const static uint32_t unsupported[] = {
    0,
    YAMI_FOURCC_411P,
    YAMI_FOURCC_ARGB,
};

UTILS_TEST(getPlaneResolution)
{

    uint32_t width = 1920;
    uint32_t height = 1080;
    uint32_t planes;
    uint32_t w[3];
    uint32_t h[3];

    for (size_t i = 0; i < N_ELEMENTS(unsupported); i++) {
        EXPECT_FALSE(getPlaneResolution(unsupported[i], 1920, 1080, w, h, planes));
        EXPECT_EQ(0u, planes);
    }
    for (size_t i = 0; i < N_ELEMENTS(bppEntrys); i++) {
        const BppEntry& e = bppEntrys[i];
        EXPECT_TRUE(getPlaneResolution(e.fourcc, width, height, w, h, planes));
        EXPECT_EQ(e.planes, planes);

        float bpp;
        uint32_t bytes = 0;
        for (uint32_t p = 0; p < planes; p++) {
            bytes += w[p] * h[p];
        }
        bpp = (float)bytes / (width * height);
        EXPECT_FLOAT_EQ(e.bpp, bpp);
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 Cloudera 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.

#include "util/impalad-metrics.h"

#include "util/debug-util.h"

using namespace std;

namespace impala {

// Naming convention: Components should be separated by '.' and words should
// be separated by '-'.
const char* ImpaladMetricKeys::IMPALA_SERVER_START_TIME =
    "impala-server.start-time";
const char* ImpaladMetricKeys::IMPALA_SERVER_VERSION =
    "impala-server.version";
const char* ImpaladMetricKeys::IMPALA_SERVER_READY =
    "impala-server.ready";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES =
    "impala-server.num-queries";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS =
    "impala-server.num-fragments";
const char* ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED =
    "impala-server.scan-ranges.total";
const char* ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID =
    "impala-server.scan-ranges.num-missing-volume-id";
const char* ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES =
    "impala-server.mem-pool.total-bytes";
const char* ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES =
    "impala-server.hash-table.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES =
    "impala-server.io-mgr.num-open-files";
const char* ImpaladMetricKeys::IO_MGR_NUM_BUFFERS =
    "impala-server.io-mgr.num-buffers";
const char* ImpaladMetricKeys::IO_MGR_TOTAL_BYTES =
    "impala-server.io-mgr.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS =
    "impala-server.io-mgr.num-unused-buffers";
const char* ImpaladMetricKeys::IO_MGR_BYTES_READ =
    "impala-server.io-mgr.bytes-read";
const char* ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ =
    "impala-server.io-mgr.local-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ =
    "impala-server.io-mgr.short-circuit-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ =
    "impala-server.io-mgr.cached-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN =
    "impala-server.io-mgr.bytes-written";
const char* ImpaladMetricKeys::CATALOG_NUM_DBS =
    "catalog.num-databases";
const char* ImpaladMetricKeys::CATALOG_NUM_TABLES =
    "catalog.num-tables";
const char* ImpaladMetricKeys::CATALOG_READY =
    "catalog.ready";
const char* ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT =
    "impala-server.num-files-open-for-insert";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS =
    "impala-server.num-open-hiveserver2-sessions";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS =
    "impala-server.num-open-beeswax-sessions";
const char* ImpaladMetricKeys::NUM_SESSIONS_EXPIRED =
    "impala-server.num-sessions-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_EXPIRED =
    "impala-server.num-queries-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_SPILLED =
    "impala-server.num-queries-spilled";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS =
    "impala-server.resultset-cache.total-num-rows";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES =
    "impala-server.resultset-cache.total-bytes";

// These are created by impala-server during startup.
// =======
// Counters
IntGauge* ImpaladMetrics::HASH_TABLE_TOTAL_BYTES = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_FRAGMENTS = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_QUERIES = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_EXPIRED = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_SPILLED = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_MISSING_VOLUME_ID = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_PROCESSED = NULL;
IntCounter* ImpaladMetrics::NUM_SESSIONS_EXPIRED = NULL;

// Gauges
IntGauge* ImpaladMetrics::CATALOG_NUM_DBS = NULL;
IntGauge* ImpaladMetrics::CATALOG_NUM_TABLES = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_OPEN_FILES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_UNUSED_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_LOCAL_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_SHORT_CIRCUIT_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_CACHED_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_WRITTEN = NULL;
IntGauge* ImpaladMetrics::MEM_POOL_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::NUM_FILES_OPEN_FOR_INSERT = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_NUM_ROWS = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_BYTES = NULL;

// Properties
BooleanProperty* ImpaladMetrics::CATALOG_READY = NULL;
BooleanProperty* ImpaladMetrics::IMPALA_SERVER_READY = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_START_TIME = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_VERSION = NULL;

void ImpaladMetrics::CreateMetrics(MetricGroup* m) {
  // Initialize impalad metrics
  IMPALA_SERVER_START_TIME = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_START_TIME, "");
  IMPALA_SERVER_VERSION = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_VERSION, GetVersionString(true));
  IMPALA_SERVER_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::IMPALA_SERVER_READY, false);

  IMPALA_SERVER_NUM_QUERIES = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES, 0L);
  NUM_QUERIES_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_EXPIRED, 0L);
  NUM_QUERIES_SPILLED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_SPILLED, 0L);
  IMPALA_SERVER_NUM_FRAGMENTS = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS, 0L);
  IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS, 0L);
  IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS, 0L);
  NUM_SESSIONS_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_SESSIONS_EXPIRED, 0L);
  RESULTSET_CACHE_TOTAL_NUM_ROWS = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS, 0L);
  RESULTSET_CACHE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES, 0L);

  // Initialize scan node metrics
  NUM_RANGES_PROCESSED = m->AddCounter(
      ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED, 0L);
  NUM_RANGES_MISSING_VOLUME_ID = m->AddCounter(
      ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID, 0L);

  // Initialize memory usage metrics
  MEM_POOL_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES, 0L, TUnit::BYTES);
  HASH_TABLE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES, 0L, TUnit::BYTES);

  // Initialize insert metrics
  NUM_FILES_OPEN_FOR_INSERT = m->AddGauge<int64_t>(
      ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT, 0L);

  // Initialize IO mgr metrics
  IO_MGR_NUM_OPEN_FILES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES, 0L);
  IO_MGR_NUM_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_BUFFERS, 0L);
  IO_MGR_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_TOTAL_BYTES, 0L, TUnit::BYTES);
  IO_MGR_NUM_UNUSED_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS, 0L);

  IO_MGR_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_LOCAL_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_CACHED_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_SHORT_CIRCUIT_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_BYTES_WRITTEN = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN, 0L);

  // Initialize catalog metrics
  CATALOG_NUM_DBS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_DBS, 0L);
  CATALOG_NUM_TABLES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_TABLES, 0L);
  CATALOG_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::CATALOG_READY, false);
}

}
<commit_msg>Use BYTES unit for the io-mgr-bytes-written metric.<commit_after>// Copyright 2012 Cloudera 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.

#include "util/impalad-metrics.h"

#include "util/debug-util.h"

using namespace std;

namespace impala {

// Naming convention: Components should be separated by '.' and words should
// be separated by '-'.
const char* ImpaladMetricKeys::IMPALA_SERVER_START_TIME =
    "impala-server.start-time";
const char* ImpaladMetricKeys::IMPALA_SERVER_VERSION =
    "impala-server.version";
const char* ImpaladMetricKeys::IMPALA_SERVER_READY =
    "impala-server.ready";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES =
    "impala-server.num-queries";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS =
    "impala-server.num-fragments";
const char* ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED =
    "impala-server.scan-ranges.total";
const char* ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID =
    "impala-server.scan-ranges.num-missing-volume-id";
const char* ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES =
    "impala-server.mem-pool.total-bytes";
const char* ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES =
    "impala-server.hash-table.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES =
    "impala-server.io-mgr.num-open-files";
const char* ImpaladMetricKeys::IO_MGR_NUM_BUFFERS =
    "impala-server.io-mgr.num-buffers";
const char* ImpaladMetricKeys::IO_MGR_TOTAL_BYTES =
    "impala-server.io-mgr.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS =
    "impala-server.io-mgr.num-unused-buffers";
const char* ImpaladMetricKeys::IO_MGR_BYTES_READ =
    "impala-server.io-mgr.bytes-read";
const char* ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ =
    "impala-server.io-mgr.local-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ =
    "impala-server.io-mgr.short-circuit-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ =
    "impala-server.io-mgr.cached-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN =
    "impala-server.io-mgr.bytes-written";
const char* ImpaladMetricKeys::CATALOG_NUM_DBS =
    "catalog.num-databases";
const char* ImpaladMetricKeys::CATALOG_NUM_TABLES =
    "catalog.num-tables";
const char* ImpaladMetricKeys::CATALOG_READY =
    "catalog.ready";
const char* ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT =
    "impala-server.num-files-open-for-insert";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS =
    "impala-server.num-open-hiveserver2-sessions";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS =
    "impala-server.num-open-beeswax-sessions";
const char* ImpaladMetricKeys::NUM_SESSIONS_EXPIRED =
    "impala-server.num-sessions-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_EXPIRED =
    "impala-server.num-queries-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_SPILLED =
    "impala-server.num-queries-spilled";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS =
    "impala-server.resultset-cache.total-num-rows";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES =
    "impala-server.resultset-cache.total-bytes";

// These are created by impala-server during startup.
// =======
// Counters
IntGauge* ImpaladMetrics::HASH_TABLE_TOTAL_BYTES = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_FRAGMENTS = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_QUERIES = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_EXPIRED = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_SPILLED = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_MISSING_VOLUME_ID = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_PROCESSED = NULL;
IntCounter* ImpaladMetrics::NUM_SESSIONS_EXPIRED = NULL;

// Gauges
IntGauge* ImpaladMetrics::CATALOG_NUM_DBS = NULL;
IntGauge* ImpaladMetrics::CATALOG_NUM_TABLES = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_OPEN_FILES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_UNUSED_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_LOCAL_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_SHORT_CIRCUIT_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_CACHED_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_WRITTEN = NULL;
IntGauge* ImpaladMetrics::MEM_POOL_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::NUM_FILES_OPEN_FOR_INSERT = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_NUM_ROWS = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_BYTES = NULL;

// Properties
BooleanProperty* ImpaladMetrics::CATALOG_READY = NULL;
BooleanProperty* ImpaladMetrics::IMPALA_SERVER_READY = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_START_TIME = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_VERSION = NULL;

void ImpaladMetrics::CreateMetrics(MetricGroup* m) {
  // Initialize impalad metrics
  IMPALA_SERVER_START_TIME = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_START_TIME, "");
  IMPALA_SERVER_VERSION = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_VERSION, GetVersionString(true));
  IMPALA_SERVER_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::IMPALA_SERVER_READY, false);

  IMPALA_SERVER_NUM_QUERIES = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES, 0L);
  NUM_QUERIES_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_EXPIRED, 0L);
  NUM_QUERIES_SPILLED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_SPILLED, 0L);
  IMPALA_SERVER_NUM_FRAGMENTS = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS, 0L);
  IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS, 0L);
  IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS, 0L);
  NUM_SESSIONS_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_SESSIONS_EXPIRED, 0L);
  RESULTSET_CACHE_TOTAL_NUM_ROWS = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS, 0L);
  RESULTSET_CACHE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES, 0L);

  // Initialize scan node metrics
  NUM_RANGES_PROCESSED = m->AddCounter(
      ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED, 0L);
  NUM_RANGES_MISSING_VOLUME_ID = m->AddCounter(
      ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID, 0L);

  // Initialize memory usage metrics
  MEM_POOL_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES, 0L, TUnit::BYTES);
  HASH_TABLE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES, 0L, TUnit::BYTES);

  // Initialize insert metrics
  NUM_FILES_OPEN_FOR_INSERT = m->AddGauge<int64_t>(
      ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT, 0L);

  // Initialize IO mgr metrics
  IO_MGR_NUM_OPEN_FILES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES, 0L);
  IO_MGR_NUM_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_BUFFERS, 0L);
  IO_MGR_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_TOTAL_BYTES, 0L, TUnit::BYTES);
  IO_MGR_NUM_UNUSED_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS, 0L);

  IO_MGR_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_LOCAL_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_CACHED_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_SHORT_CIRCUIT_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_BYTES_WRITTEN = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN, 0L, TUnit::BYTES);

  // Initialize catalog metrics
  CATALOG_NUM_DBS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_DBS, 0L);
  CATALOG_NUM_TABLES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_TABLES, 0L);
  CATALOG_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::CATALOG_READY, false);
}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// A benchmark designed to isolate the constant overheads of picture recording.
// We record a very tiny (one op) picture; one op is better than none, as it forces
// us to allocate memory to store that op... we can't just cheat by holding onto NULLs.

#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkPictureRecorder.h"

struct PictureOverheadBench : public Benchmark {
    const char* onGetName() override { return "picture_overhead"; }
    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }

    void onDraw(const int loops, SkCanvas*) override {
        SkPictureRecorder rec;
        for (int i = 0; i < loops; i++) {
            SkCanvas* c = rec.beginRecording(SkRect::MakeWH(2000,3000));
                c->drawRect(SkRect::MakeXYWH(10, 10, 1000, 1000), SkPaint());
            SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
        }
    }
};
DEF_BENCH(return new PictureOverheadBench;)
<commit_msg>Expand bench to cover no-draw SkPictures too.<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// A benchmark designed to isolate the constant overheads of picture recording.
// We record an empty picture and a picture with one draw op to force memory allocation.

#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkPictureRecorder.h"

template <bool kDraw>
struct PictureOverheadBench : public Benchmark {
    const char* onGetName() override {
        return kDraw ? "picture_overhead_draw" : "picture_overhead_nodraw";
    }
    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }

    void onDraw(const int loops, SkCanvas*) override {
        SkPictureRecorder rec;
        for (int i = 0; i < loops; i++) {
            rec.beginRecording(SkRect::MakeWH(2000,3000));
            if (kDraw) {
                rec.getRecordingCanvas()->drawRect(SkRect::MakeXYWH(10, 10, 1000, 1000), SkPaint());
            }
            SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
        }
    }
};

DEF_BENCH(return (new PictureOverheadBench<false>);)
DEF_BENCH(return (new PictureOverheadBench< true>);)
<|endoftext|>


<commit_before>/*******************************************************************************
* Copyright 2016 ROBOTIS CO., LTD.
*
* 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.
*******************************************************************************/

/* Authors: Darby Limm, Hye-Jong KIM */

#ifndef OMAPI_HPP_
#define OMAPI_HPP_

#include <RTOS.h>

#include "OMManager.hpp"
#include "OMMath.hpp"
#include "OMKinematics.hpp"
#include "OMDynamixel.hpp"

namespace OPEN_MANIPULATOR
{
template <uint8_t DXL_SIZE, uint32_t BAUD_RATE>
OMDynamixel omDynamixel

void initDynamixel()
{
  // OMDynamixel<DYNAMIXEL::DXL_SIZE,DYNAMIXEL::BAUD_RATE> omDynamixel;

    // omDynamixel.init();
  // omDynamixel.setDisable(1);
  // omDynamixel.setPositionControlMode(1);
  // omDynamixel.setEnable(1);

    // float* angle = omDynamixel.getAngle();
  // Serial.print("angle : "); Serial.println(angle[0]);

    static uint32_t loop_cnt = 0;

  Serial.print("Loop Cnt : ");
  Serial.println(loop_cnt++);
}

void Thread_Robot_State(void const *argument)
{
  (void) argument;

  // pinMode(13, OUTPUT);

  // static bool index = false;

  for(;;)
  {
    // if (index)
    //   omDynamixel.setAngle(1, 0.0);
    // else
    //   omDynamixel.setAngle(1, 1.0);

    // index = !index;
    // digitalWrite(13, !digitalRead(13));
    static uint32_t robot_state_cnt = 0;

    Serial.print("Robot State Cnt : ");
    Serial.println(robot_state_cnt++);
    osDelay(300);
  }
}
}

///////////////////////////////////////get(joint level)//////////////////////////////////////

///////////////////////////////////////set(joint level)//////////////////////////////////////

///////////////////////////////////////get(position level)///////////////////////////////////

///////////////////////////////////////set(position level)///////////////////////////////////

#endif // OMAPI_HPP_

  <commit_msg>add config for thread<commit_after>/*******************************************************************************
* Copyright 2016 ROBOTIS CO., LTD.
*
* 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.
*******************************************************************************/

/* Authors: Darby Limm, Hye-Jong KIM */

#ifndef OMAPI_HPP_
#define OMAPI_HPP_

#include <RTOS.h>

#include "OMDebug.hpp"
#include "OMManager.hpp"
#include "OMMath.hpp"
#include "OMKinematics.hpp"
#include "OMDynamixel.hpp"
#include "OMPath.hpp"

osMutexDef(om_mutex);
osMutexId(om_mutex_id);

namespace MUTEX
{
void create(){ om_mutex_id = osMutexCreate(osMutex(om_mutex)); }
void wait(){ osMutexWait(om_mutex_id, osWaitForever); }
void release(){ osMutexRelease(om_mutex_id); }
} // namespace THREAD

namespace OPEN_MANIPULATOR
{
namespace ACTUATOR
{
bool (*setAllJointAngle)(float*) = NULL;
bool (*setJointAngle)(uint8_t, float) = NULL;
float* (*getAngle)() = NULL;
} // namespace ACTUATOR

void linkSetAllJointAnglefunctionToAPI(bool (*fp)(float*)){ ACTUATOR::setAllJointAngle = fp; }
void linkSetJointAnglefunctionToAPI(bool (*fp)(uint8_t, float)){ ACTUATOR::setJointAngle = fp; }
void linkSetGetAnglefunctionToAPI(float* (*fp)()){ ACTUATOR::getAngle = fp; }

// get(position level)

// set(position level)

void Thread_Robot_State(void const *argument)
{
  (void) argument;

  LOG::init();
  MUTEX::create();

  for(;;)
  {
  MUTEX::wait();
    float* angle_ptr = ACTUATOR::getAngle();
  MUTEX::release();
    LOG::INFO("angle : " + String(angle_ptr[0]));

  osDelay(10);
  }
}
} // namespace OPEN_MANIPULATOR

#endif // OMAPI_HPP_

  <|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// This flag changes the implementation to use S60 CDcoumentHandler
// instead of apparch when opening the files
#define USE_DOCUMENTHANDLER

#include <qcoreapplication.h>
#include <qdir.h>
#include <qurl.h>
#include <private/qcore_symbian_p.h>

#include <miutset.h>                // KUidMsgTypeSMTP
#include <txtrich.h>                // CRichText
#include <f32file.h>                // TDriveUnit etc
#include <eikenv.h>                 // CEikonEnv
#include <apgcli.h>                 // RApaLsSession
#include <apgtask.h>                // TApaTaskList, TApaTask
#include <rsendas.h>                // RSendAs
#include <rsendasmessage.h>         // RSendAsMessage

#ifdef Q_WS_S60
#  include <pathinfo.h>             // PathInfo
#  ifdef USE_DOCUMENTHANDLER
#    include <documenthandler.h>    // CDocumentHandler
#    include <aknserverapp.h>
#  endif
#else
#  warning CDocumentHandler requires support for S60
#  undef USE_DOCUMENTHANDLER        // Fallback to RApaLsSession based implementation
#endif

QT_BEGIN_NAMESPACE

_LIT(KCacheSubDir, "Cache\\");
_LIT(KSysBin, "\\Sys\\Bin\\");
_LIT(KBrowserPrefix, "4 " );
_LIT(KFontsDir, "z:\\resource\\Fonts\\");
const TUid KUidBrowser = { 0x10008D39 };

template<class R>
class QAutoClose
{
public:
    QAutoClose(R& aObj) : mPtr(&aObj) {}
    ~QAutoClose()
    {
        if (mPtr)
            mPtr->Close();
    }
    void Forget()
    {
        mPtr = 0;
    }
private:
    QAutoClose(const QAutoClose&);
    QAutoClose& operator=(const QAutoClose&);
private:
    R* mPtr;
};

#ifdef USE_DOCUMENTHANDLER
class QS60DocumentHandler : public MAknServerAppExitObserver
{
public:
    QS60DocumentHandler() :docHandler(0) {}

    ~QS60DocumentHandler() {
        delete docHandler;
    }

    CDocumentHandler& documentHandler() {
        // In case user calls openUrl twice subsequently, before the first embedded app is closed
        // we use the same CDocumentHandler instance. Using same instance makes sure the first
        // launched embedded app is closed and latter one gets embedded to our app.
        // Using different instance would help only theoretically since user cannot interact with
        // several embedded apps at the same time.
        if(!docHandler) {
            QT_TRAP_THROWING(docHandler = CDocumentHandler::NewL());
            docHandler->SetExitObserver(this);
        }
        return *docHandler;
    }

private: // From MAknServerAppExitObserver
    void HandleServerAppExit(TInt /*aReason*/) {
        delete docHandler;
        docHandler = 0;
    }

private:
    CDocumentHandler* docHandler;
};
Q_GLOBAL_STATIC(QS60DocumentHandler, qt_s60_documenthandler);
#endif

static void handleMailtoSchemeLX(const QUrl &url)
{
    // this function has many intermingled leaves and throws. Qt and Symbian objects do not have
    // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack.
    QString recipient = url.path();
    QString subject = url.queryItemValue(QLatin1String("subject"));
    QString body = url.queryItemValue(QLatin1String("body"));
    QString to = url.queryItemValue(QLatin1String("to"));
    QString cc = url.queryItemValue(QLatin1String("cc"));
    QString bcc = url.queryItemValue(QLatin1String("bcc"));

    // these fields might have comma separated addresses
    QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts);

    RSendAs sendAs;
    User::LeaveIfError(sendAs.Connect());
    QAutoClose<RSendAs> sendAsCleanup(sendAs);

    CSendAsAccounts* accounts = CSendAsAccounts::NewL();
    CleanupStack::PushL(accounts);
    sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
    TInt count = accounts->Count();
    CleanupStack::PopAndDestroy(accounts);

    if(!count) {
        // TODO: Task 259192: We should try to create account if count == 0
        // CSendUi would provide account creation service for us, but it requires ridicilous
        // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
        User::Leave(KErrNotSupported);
    } else {
        RSendAsMessage sendAsMessage;
        sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
        QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage);

        // Subject
        sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));

        // Body
        sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));

        // To
        foreach(QString item, recipients)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        foreach(QString item, tos)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        // Cc
        foreach(QString item, ccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc);

        // Bcc
        foreach(QString item, bccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc);

        // send the message
        sendAsMessage.LaunchEditorAndCloseL();
        // sendAsMessage is already closed
        sendAsMessageCleanup.Forget();
    }
}

static bool handleMailtoScheme(const QUrl &url)
{
    TRAPD(err, QT_TRYCATCH_LEAVING(handleMailtoSchemeLX(url)));
    return err ? false : true;
}

static void handleOtherSchemesL(const TDesC& aUrl)
{
    // Other schemes are at the moment passed to WEB browser
    HBufC* buf16 = HBufC::NewLC(aUrl.Length() + KBrowserPrefix.iTypeLength);
    buf16->Des().Copy(KBrowserPrefix); // Prefix used to launch correct browser view
    buf16->Des().Append(aUrl);

    TApaTaskList taskList(CEikonEnv::Static()->WsSession());
    TApaTask task = taskList.FindApp(KUidBrowser);
    if (task.Exists()){
        // Switch to existing browser instance
        HBufC8* param8 = HBufC8::NewLC(buf16->Length());
        param8->Des().Append(buf16->Des());
        task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used
        CleanupStack::PopAndDestroy(param8);
    } else {
        // Start a new browser instance
        RApaLsSession appArcSession;
        User::LeaveIfError(appArcSession.Connect());
        CleanupClosePushL<RApaLsSession>(appArcSession);
        TThreadId id;
        appArcSession.StartDocument(*buf16, KUidBrowser, id);
        CleanupStack::PopAndDestroy(); // appArcSession
    }

    CleanupStack::PopAndDestroy(buf16);
}

static bool handleOtherSchemes(const QUrl &url)
{
    QString encUrl(QString::fromUtf8(url.toEncoded()));
    TPtrC urlPtr(qt_QString2TPtrC(encUrl));
    TRAPD( err, handleOtherSchemesL(urlPtr));
    return err ? false : true;
}

static TDriveUnit exeDrive()
{
    RProcess me;
    TFileName processFileName = me.FileName();
    TDriveUnit drive(processFileName);
    return drive;
}

static TDriveUnit writableExeDrive()
{
    TDriveUnit drive = exeDrive();
    if(drive.operator TInt() == EDriveZ)
        return TDriveUnit(EDriveC);
    return drive;
}

static TPtrC writableDataRoot()
{
    TDriveUnit drive = exeDrive();
#ifdef Q_WS_S60
    switch(drive.operator TInt()){
        case EDriveC:
            return PathInfo::PhoneMemoryRootPath();
            break;
        case EDriveE:
            return PathInfo::MemoryCardRootPath();
            break;
        case EDriveZ:
            // It is not possible to write on ROM drive ->
            // return phone mem root path instead
            return PathInfo::PhoneMemoryRootPath();
            break;
        default:
            return PathInfo::PhoneMemoryRootPath();
            break;
    }
#else
#warning No fallback implementation of writableDataRoot()
    return 0;
#endif
}

static void openDocumentL(const TDesC& aUrl)
{
#ifndef USE_DOCUMENTHANDLER
    // Start app associated to file MIME type by using RApaLsSession
    // Apparc base method cannot be used to open app in embedded mode,
    // but seems to be most stable way at the moment
    RApaLsSession appArcSession;
    User::LeaveIfError(appArcSession.Connect());
    CleanupClosePushL<RApaLsSession>(appArcSession);
    TThreadId id;
    // ESwitchFiles means do not start another instance
    // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
    User::LeaveIfError(appArcSession.StartDocument(aUrl, id,
            RApaLsSession::ESwitchFiles)); // ELaunchNewApp
    CleanupStack::PopAndDestroy(); // appArcSession
#else
    // This is an alternative way to launch app associated to MIME type
    // CDocumentHandler also supports opening apps in embedded mode.
    TDataType temp;
    qt_s60_documenthandler()->documentHandler().OpenFileEmbeddedL(aUrl, temp);
#endif
}

#ifdef USE_SCHEMEHANDLER
// The schemehandler component only exist in private SDK. This implementation
// exist here just for convenience in case that we need to use it later on
// The schemehandle based implementation is not yet tested.

// The biggest advantage of schemehandler is that it can handle
// wide range of schemes and is extensible by plugins
static bool handleUrl(const QUrl &url)
{
    if (!url.isValid())
        return false;

    QString urlString(url.toString());
    TPtrC urlPtr(qt_QString2TPtrC(urlString));
    TRAPD( err, handleUrlL(urlPtr));
    return err ? false : true;
}

static void handleUrlL(const TDesC& aUrl)
{
    CSchemeHandler* schemeHandler = CSchemeHandler::NewL(aUrl);
    CleanupStack::PushL(schemeHandler);
    schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
    CleanupStack::PopAndDestroy();
}
static bool launchWebBrowser(const QUrl &url)
{
    return handleUrl(url);
}

static bool openDocument(const QUrl &file)
{
    return handleUrl(url);
}
#endif

static bool launchWebBrowser(const QUrl &url)
{
    if (!url.isValid())
        return false;

    if (url.scheme() == QLatin1String("mailto")) {
        return handleMailtoScheme(url);
    }
    return handleOtherSchemes( url );
}

static bool openDocument(const QUrl &file)
{
    if (!file.isValid())
        return false;

    QString filePath = file.toLocalFile();
    filePath = QDir::toNativeSeparators(filePath);
    TPtrC filePathPtr(qt_QString2TPtrC(filePath));
    TRAPD(err, openDocumentL(filePathPtr));
    return err ? false : true;
}

QString QDesktopServices::storageLocation(StandardLocation type)
{
    TFileName path;

    switch (type) {
    case DesktopLocation:
        qWarning("No desktop concept in Symbian OS");
        // But lets still use some feasible default
        path.Append(writableDataRoot());
        break;
    case DocumentsLocation:
        path.Append(writableDataRoot());
        break;
    case FontsLocation:
        path.Append(KFontsDir);
        break;
    case ApplicationsLocation:
        path.Append(exeDrive().Name());
        path.Append(KSysBin);
        break;
    case MusicLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::SoundsPath());
#endif
        break;
    case MoviesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::VideosPath());
#endif
        break;
    case PicturesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::ImagesPath());
#endif
        break;
    case TempLocation:
        return QDir::tempPath();
        break;
    case HomeLocation:
        path.Append(writableDataRoot());
        //return QDir::homePath(); break;
        break;
    case DataLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        break;
    case CacheLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        path.Append(KCacheSubDir);
        break;
    default:
        // Lets use feasible default
        path.Append(writableDataRoot());
        break;
    }

    // Convert to cross-platform format and clean the path
    QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
    QString qtPath = QDir::fromNativeSeparators(nativePath);
    qtPath = QDir::cleanPath(qtPath);

    // Note: The storage location returned can be a directory that does not exist;
    // i.e., it may need to be created by the system or the user.
    return  qtPath;
}

typedef QString (*LocalizerFunc)(QString&);

static QString defaultLocalizedDirectoryName(QString&)
{
    return QString();
}

QString QDesktopServices::displayName(StandardLocation type)
{
    static LocalizerFunc ptrLocalizerFunc = NULL;

    if (!ptrLocalizerFunc) {
        ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
            (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
        if (!ptrLocalizerFunc)
            ptrLocalizerFunc = &defaultLocalizedDirectoryName;
    }

    QString rawPath = storageLocation(type);
    return ptrLocalizerFunc(rawPath);
}

QT_END_NAMESPACE
<commit_msg>Fixing QDesktopServices so that file server session can be accessed from secondary thread.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// This flag changes the implementation to use S60 CDcoumentHandler
// instead of apparch when opening the files
#define USE_DOCUMENTHANDLER

#include <qcoreapplication.h>
#include <qdir.h>
#include <qurl.h>
#include <private/qcore_symbian_p.h>

#include <miutset.h>                // KUidMsgTypeSMTP
#include <txtrich.h>                // CRichText
#include <f32file.h>                // TDriveUnit etc
#include <eikenv.h>                 // CEikonEnv
#include <apgcli.h>                 // RApaLsSession
#include <apgtask.h>                // TApaTaskList, TApaTask
#include <rsendas.h>                // RSendAs
#include <rsendasmessage.h>         // RSendAsMessage

#ifdef Q_WS_S60
#  include <pathinfo.h>             // PathInfo
#  ifdef USE_DOCUMENTHANDLER
#    include <documenthandler.h>    // CDocumentHandler
#    include <aknserverapp.h>
#  endif
#else
#  warning CDocumentHandler requires support for S60
#  undef USE_DOCUMENTHANDLER        // Fallback to RApaLsSession based implementation
#endif

QT_BEGIN_NAMESPACE

_LIT(KCacheSubDir, "Cache\\");
_LIT(KSysBin, "\\Sys\\Bin\\");
_LIT(KBrowserPrefix, "4 " );
_LIT(KFontsDir, "z:\\resource\\Fonts\\");
const TUid KUidBrowser = { 0x10008D39 };

template<class R>
class QAutoClose
{
public:
    QAutoClose(R& aObj) : mPtr(&aObj) {}
    ~QAutoClose()
    {
        if (mPtr)
            mPtr->Close();
    }
    void Forget()
    {
        mPtr = 0;
    }
private:
    QAutoClose(const QAutoClose&);
    QAutoClose& operator=(const QAutoClose&);
private:
    R* mPtr;
};

#ifdef USE_DOCUMENTHANDLER
class QS60DocumentHandler : public MAknServerAppExitObserver
{
public:
    QS60DocumentHandler() :docHandler(0) {}

    ~QS60DocumentHandler() {
        delete docHandler;
    }

    CDocumentHandler& documentHandler() {
        // In case user calls openUrl twice subsequently, before the first embedded app is closed
        // we use the same CDocumentHandler instance. Using same instance makes sure the first
        // launched embedded app is closed and latter one gets embedded to our app.
        // Using different instance would help only theoretically since user cannot interact with
        // several embedded apps at the same time.
        if(!docHandler) {
            QT_TRAP_THROWING(docHandler = CDocumentHandler::NewL());
            docHandler->SetExitObserver(this);
        }
        return *docHandler;
    }

private: // From MAknServerAppExitObserver
    void HandleServerAppExit(TInt /*aReason*/) {
        delete docHandler;
        docHandler = 0;
    }

private:
    CDocumentHandler* docHandler;
};
Q_GLOBAL_STATIC(QS60DocumentHandler, qt_s60_documenthandler);
#endif

static void handleMailtoSchemeLX(const QUrl &url)
{
    // this function has many intermingled leaves and throws. Qt and Symbian objects do not have
    // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack.
    QString recipient = url.path();
    QString subject = url.queryItemValue(QLatin1String("subject"));
    QString body = url.queryItemValue(QLatin1String("body"));
    QString to = url.queryItemValue(QLatin1String("to"));
    QString cc = url.queryItemValue(QLatin1String("cc"));
    QString bcc = url.queryItemValue(QLatin1String("bcc"));

    // these fields might have comma separated addresses
    QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts);

    RSendAs sendAs;
    User::LeaveIfError(sendAs.Connect());
    QAutoClose<RSendAs> sendAsCleanup(sendAs);

    CSendAsAccounts* accounts = CSendAsAccounts::NewL();
    CleanupStack::PushL(accounts);
    sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
    TInt count = accounts->Count();
    CleanupStack::PopAndDestroy(accounts);

    if(!count) {
        // TODO: Task 259192: We should try to create account if count == 0
        // CSendUi would provide account creation service for us, but it requires ridicilous
        // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
        User::Leave(KErrNotSupported);
    } else {
        RSendAsMessage sendAsMessage;
        sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
        QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage);

        // Subject
        sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));

        // Body
        sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));

        // To
        foreach(QString item, recipients)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        foreach(QString item, tos)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        // Cc
        foreach(QString item, ccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc);

        // Bcc
        foreach(QString item, bccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc);

        // send the message
        sendAsMessage.LaunchEditorAndCloseL();
        // sendAsMessage is already closed
        sendAsMessageCleanup.Forget();
    }
}

static bool handleMailtoScheme(const QUrl &url)
{
    TRAPD(err, QT_TRYCATCH_LEAVING(handleMailtoSchemeLX(url)));
    return err ? false : true;
}

static void handleOtherSchemesL(const TDesC& aUrl)
{
    // Other schemes are at the moment passed to WEB browser
    HBufC* buf16 = HBufC::NewLC(aUrl.Length() + KBrowserPrefix.iTypeLength);
    buf16->Des().Copy(KBrowserPrefix); // Prefix used to launch correct browser view
    buf16->Des().Append(aUrl);

    TApaTaskList taskList(CEikonEnv::Static()->WsSession());
    TApaTask task = taskList.FindApp(KUidBrowser);
    if (task.Exists()){
        // Switch to existing browser instance
        HBufC8* param8 = HBufC8::NewLC(buf16->Length());
        param8->Des().Append(buf16->Des());
        task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used
        CleanupStack::PopAndDestroy(param8);
    } else {
        // Start a new browser instance
        RApaLsSession appArcSession;
        User::LeaveIfError(appArcSession.Connect());
        CleanupClosePushL<RApaLsSession>(appArcSession);
        TThreadId id;
        appArcSession.StartDocument(*buf16, KUidBrowser, id);
        CleanupStack::PopAndDestroy(); // appArcSession
    }

    CleanupStack::PopAndDestroy(buf16);
}

static bool handleOtherSchemes(const QUrl &url)
{
    QString encUrl(QString::fromUtf8(url.toEncoded()));
    TPtrC urlPtr(qt_QString2TPtrC(encUrl));
    TRAPD( err, handleOtherSchemesL(urlPtr));
    return err ? false : true;
}

static TDriveUnit exeDrive()
{
    RProcess me;
    TFileName processFileName = me.FileName();
    TDriveUnit drive(processFileName);
    return drive;
}

static TDriveUnit writableExeDrive()
{
    TDriveUnit drive = exeDrive();
    if(drive.operator TInt() == EDriveZ)
        return TDriveUnit(EDriveC);
    return drive;
}

static TPtrC writableDataRoot()
{
    TDriveUnit drive = exeDrive();
#ifdef Q_WS_S60
    switch(drive.operator TInt()){
        case EDriveC:
            return PathInfo::PhoneMemoryRootPath();
            break;
        case EDriveE:
            return PathInfo::MemoryCardRootPath();
            break;
        case EDriveZ:
            // It is not possible to write on ROM drive ->
            // return phone mem root path instead
            return PathInfo::PhoneMemoryRootPath();
            break;
        default:
            return PathInfo::PhoneMemoryRootPath();
            break;
    }
#else
#warning No fallback implementation of writableDataRoot()
    return 0;
#endif
}

static void openDocumentL(const TDesC& aUrl)
{
#ifndef USE_DOCUMENTHANDLER
    // Start app associated to file MIME type by using RApaLsSession
    // Apparc base method cannot be used to open app in embedded mode,
    // but seems to be most stable way at the moment
    RApaLsSession appArcSession;
    User::LeaveIfError(appArcSession.Connect());
    CleanupClosePushL<RApaLsSession>(appArcSession);
    TThreadId id;
    // ESwitchFiles means do not start another instance
    // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
    User::LeaveIfError(appArcSession.StartDocument(aUrl, id,
            RApaLsSession::ESwitchFiles)); // ELaunchNewApp
    CleanupStack::PopAndDestroy(); // appArcSession
#else
    // This is an alternative way to launch app associated to MIME type
    // CDocumentHandler also supports opening apps in embedded mode.
    TDataType temp;
    qt_s60_documenthandler()->documentHandler().OpenFileEmbeddedL(aUrl, temp);
#endif
}

#ifdef USE_SCHEMEHANDLER
// The schemehandler component only exist in private SDK. This implementation
// exist here just for convenience in case that we need to use it later on
// The schemehandle based implementation is not yet tested.

// The biggest advantage of schemehandler is that it can handle
// wide range of schemes and is extensible by plugins
static bool handleUrl(const QUrl &url)
{
    if (!url.isValid())
        return false;

    QString urlString(url.toString());
    TPtrC urlPtr(qt_QString2TPtrC(urlString));
    TRAPD( err, handleUrlL(urlPtr));
    return err ? false : true;
}

static void handleUrlL(const TDesC& aUrl)
{
    CSchemeHandler* schemeHandler = CSchemeHandler::NewL(aUrl);
    CleanupStack::PushL(schemeHandler);
    schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
    CleanupStack::PopAndDestroy();
}
static bool launchWebBrowser(const QUrl &url)
{
    return handleUrl(url);
}

static bool openDocument(const QUrl &file)
{
    return handleUrl(url);
}
#endif

static bool launchWebBrowser(const QUrl &url)
{
    if (!url.isValid())
        return false;

    if (url.scheme() == QLatin1String("mailto")) {
        return handleMailtoScheme(url);
    }
    return handleOtherSchemes( url );
}

static bool openDocument(const QUrl &file)
{
    if (!file.isValid())
        return false;

    QString filePath = file.toLocalFile();
    filePath = QDir::toNativeSeparators(filePath);
    TPtrC filePathPtr(qt_QString2TPtrC(filePath));
    TRAPD(err, openDocumentL(filePathPtr));
    return err ? false : true;
}

QString QDesktopServices::storageLocation(StandardLocation type)
{
    TFileName path;

    switch (type) {
    case DesktopLocation:
        qWarning("No desktop concept in Symbian OS");
        // But lets still use some feasible default
        path.Append(writableDataRoot());
        break;
    case DocumentsLocation:
        path.Append(writableDataRoot());
        break;
    case FontsLocation:
        path.Append(KFontsDir);
        break;
    case ApplicationsLocation:
        path.Append(exeDrive().Name());
        path.Append(KSysBin);
        break;
    case MusicLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::SoundsPath());
#endif
        break;
    case MoviesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::VideosPath());
#endif
        break;
    case PicturesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::ImagesPath());
#endif
        break;
    case TempLocation:
        return QDir::tempPath();
        break;
    case HomeLocation:
        path.Append(writableDataRoot());
        //return QDir::homePath(); break;
        break;
    case DataLocation:
        qt_s60GetRFs().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        break;
    case CacheLocation:
        qt_s60GetRFs().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        path.Append(KCacheSubDir);
        break;
    default:
        // Lets use feasible default
        path.Append(writableDataRoot());
        break;
    }

    // Convert to cross-platform format and clean the path
    QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
    QString qtPath = QDir::fromNativeSeparators(nativePath);
    qtPath = QDir::cleanPath(qtPath);

    // Note: The storage location returned can be a directory that does not exist;
    // i.e., it may need to be created by the system or the user.
    return  qtPath;
}

typedef QString (*LocalizerFunc)(QString&);

static QString defaultLocalizedDirectoryName(QString&)
{
    return QString();
}

QString QDesktopServices::displayName(StandardLocation type)
{
    static LocalizerFunc ptrLocalizerFunc = NULL;

    if (!ptrLocalizerFunc) {
        ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
            (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
        if (!ptrLocalizerFunc)
            ptrLocalizerFunc = &defaultLocalizedDirectoryName;
    }

    QString rawPath = storageLocation(type);
    return ptrLocalizerFunc(rawPath);
}

QT_END_NAMESPACE
<|endoftext|>