<commit_before>/*******************************************************************************
* Copyright 2009-2015 Juan Francisco Crespo Galán
*
* 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 "fx/ConvolverSound.h"
#include "fx/ImpulseResponse.h"
#include "util/ThreadPool.h"
#include "devices/DeviceManager.h"
#include "devices/IDevice.h"
#include "devices/IDeviceFactory.h"
#include "devices/IHandle.h"
#include "plugin/PluginManager.h"
#include "respec/ChannelMapper.h"
#include "respec/JOSResample.h"
#include "file/File.h"
#include "fx/DynamicMusic.h"
#include "fx/SoundList.h"
#include "fx/MutableSound.h"
#include "fx/HRTFLoader.h"
#include "fx/BinauralSound.h"

#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <vector>

#include <Windows.h>

using namespace aud;

void loadSounds(const std::string& path, const std::string& ext, std::vector<std::shared_ptr<ISound>>& outList);
int main(int argc, char* argv[])
{
	srand(time(NULL));

	PluginManager::loadPlugins("");

	auto factory = DeviceManager::getDefaultDeviceFactory();
	auto device = factory->openDevice();

	auto fftPlan(std::make_shared<FFTPlan>(2048, true));
	auto threadPool(std::make_shared<ThreadPool>(std::thread::hardware_concurrency()));
	auto hrtfs = HRTFLoader::loadRightHRTFs(fftPlan, ".wav", "hrtfs");
	auto i_ir(std::make_shared<ImpulseResponse>(std::make_shared<StreamBuffer>(std::make_shared<File>("Opti-inverse.wav")), fftPlan));
	auto source1 = std::make_shared<Source>(10, -10, 0.75);
	auto source2 = std::make_shared<Source>(30, -10, 0.75);
	auto source3 = std::make_shared<Source>(20, -10, 0.75);
	DeviceSpecs specs;
	specs.channels = CHANNELS_MONO;
	specs.rate = hrtfs->getSpecs().rate;

	std::vector<std::shared_ptr<ISound>> saberClash;
	std::vector<std::shared_ptr<ISound>> saberWield;
	loadSounds("sw/saberClash", ".wav", saberClash);
	loadSounds("sw/saberWield", ".wav", saberWield);
	auto saberSList = std::make_shared<SoundList>(true);
	for(auto s : saberClash)
		saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(std::make_shared<ChannelMapper>(s, specs), specs), hrtfs, source3, threadPool, fftPlan));
	int i = 0;
	for(auto s : saberWield)
	{
		if(i % 2 == 0)
			saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(std::make_shared<ChannelMapper>(s, specs), specs), hrtfs, source1, threadPool, fftPlan));
		if(i % 2 != 0)
			saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(std::make_shared<ChannelMapper>(s, specs), specs), hrtfs, source2, threadPool, fftPlan));
		i++;
	}
	auto saberMutableSound = std::make_shared<ConvolverSound>(std::make_shared<MutableSound>(saberSList), i_ir, threadPool, fftPlan);

	device->lock();
	auto handle = device->play(saberMutableSound);
	handle->setLoopCount(-1);
	device->unlock();

	//DynamicMusic dynamicSound(device);
	//int saberScene1 = dynamicSound.addScene(clashMutableSound);
	//int saberScene2 = dynamicSound.addScene(clashMutableSound);
	//dynamicSound.addTransition(saberScene1, saberScene2, wieldMutableSound);
	//dynamicSound.addTransition(saberScene2, saberScene1, wieldMutableSound);

	//int millis = 0;
	//while(true)
	//{
	//	dynamicSound.changeScene(saberScene1);
	//	millis = (rand() % 5000) + 5000;
	//	std::this_thread::sleep_for(std::chrono::milliseconds(millis));
	//	//dynamicSound.changeScene(saberScene2);
	//	millis = (rand() % 5000) + 5000;
	//	//std::this_thread::sleep_for(std::chrono::milliseconds(millis));
	//}

	std::this_thread::sleep_for(std::chrono::milliseconds(500000));

	return 0;
}

void loadSounds(const std::string& path, const std::string& ext, std::vector<std::shared_ptr<ISound>>& outList)
{
	std::string readpath = path;
	if(path == "")
		readpath = ".";

	WIN32_FIND_DATA entry;
	bool found_file = true;
	std::string search = readpath + "\\*";
	HANDLE dir = FindFirstFile(search.c_str(), &entry);
	if(dir == INVALID_HANDLE_VALUE)
		return;

	float azim, elev;

	while(found_file)
	{
		std::string filename = entry.cFileName;
		if(filename.length() >= ext.length() && filename.substr(filename.length() - ext.length()) == ext)
			outList.push_back(std::make_shared<File>(readpath + "/" + filename));
		found_file = FindNextFile(dir, &entry);
	}
	FindClose(dir);
	return;
}
<commit_msg>Changes to soundscene demo<commit_after>/*******************************************************************************
* Copyright 2009-2015 Juan Francisco Crespo Galán
*
* 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 "fx/ConvolverSound.h"
#include "fx/ImpulseResponse.h"
#include "util/ThreadPool.h"
#include "devices/DeviceManager.h"
#include "devices/IDevice.h"
#include "devices/IDeviceFactory.h"
#include "devices/IHandle.h"
#include "plugin/PluginManager.h"
#include "respec/JOSResample.h"
#include "file/File.h"
#include "fx/DynamicMusic.h"
#include "fx/SoundList.h"
#include "fx/MutableSound.h"
#include "fx/HRTFLoader.h"
#include "fx/BinauralSound.h"

#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <vector>

#include <Windows.h>

using namespace aud;

void loadSounds(const std::string& path, const std::string& ext, std::vector<std::shared_ptr<ISound>>& outList);
int main(int argc, char* argv[])
{
	srand(time(NULL));

	PluginManager::loadPlugins("");

	auto factory = DeviceManager::getDefaultDeviceFactory();
	auto device = factory->openDevice();

	auto fftPlan(std::make_shared<FFTPlan>(2048, true));
	auto threadPool(std::make_shared<ThreadPool>(std::thread::hardware_concurrency()));
	auto hrtfs = HRTFLoader::loadRightHRTFs(fftPlan, ".wav", "hrtfs");
	auto i_ir(std::make_shared<ImpulseResponse>(std::make_shared<StreamBuffer>(std::make_shared<File>("Opti-inverse.wav")), fftPlan));
	auto source1 = std::make_shared<Source>(210, 0, 0.5);
	auto source2 = std::make_shared<Source>(190, 0, 0.5);
	auto source3 = std::make_shared<Source>(200, 0, 0.5);
	auto sourceBlaster = std::make_shared<Source>(10, 0, 0.8);
	std::vector<std::shared_ptr<Source>> sourceBullets;
	sourceBullets.push_back(std::make_shared<Source>(10, 0, 0.9));
	sourceBullets.push_back(std::make_shared<Source>(10, 0, 0.9));
	sourceBullets.push_back(std::make_shared<Source>(10, 0, 0.9));
	sourceBullets.push_back(std::make_shared<Source>(10, 0, 0.9));
	sourceBullets.push_back(std::make_shared<Source>(10, 0, 0.9));

	DeviceSpecs specs;
	specs.channels = CHANNELS_MONO;
	specs.rate = hrtfs->getSpecs().rate;

	std::vector<std::shared_ptr<ISound>> saberClash;
	std::vector<std::shared_ptr<ISound>> saberWield;
	loadSounds("sw/saberClash", ".wav", saberClash);
	loadSounds("sw/saberWield", ".wav", saberWield);
	auto saberSList = std::make_shared<SoundList>(true);
	for(auto s : saberClash)
	{
		saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(s, specs), hrtfs, source3, threadPool, fftPlan));
	}
	int i = 0;
	for(auto s : saberWield)
	{
		if(i % 2 == 0)
			saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(s, specs), hrtfs, source1, threadPool, fftPlan));
		if(i % 2 != 0)
			saberSList->addSound(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(s, specs), hrtfs, source2, threadPool, fftPlan));
		i++;
	}
	auto saberMutableSound = std::make_shared<ConvolverSound>(std::make_shared<MutableSound>(saberSList), i_ir, threadPool, fftPlan);
	auto blasterShotSound = std::make_shared<ConvolverSound>(std::make_shared<BinauralSound>(std::make_shared<JOSResample>(std::make_shared<File>("sw/blaster/repeat-1.wav"), specs), hrtfs, sourceBlaster, threadPool, fftPlan), i_ir, threadPool, fftPlan);

	device->lock();
	auto handleSaber = device->play(saberMutableSound);
	handleSaber->setLoopCount(-1);
	device->unlock();

	std::this_thread::sleep_for(std::chrono::milliseconds(2000));

	int millis = 0;
	for(int i = 0; i < 1000; i++)
	{
		auto handleBlaster = device->play(blasterShotSound);
		millis = (rand() % 20) + 140;
		std::this_thread::sleep_for(std::chrono::milliseconds(millis));
		if(i % 5 == 0 && i != 0)
		{
			millis = (rand() % 160) + 140;
			std::this_thread::sleep_for(std::chrono::milliseconds(millis));
		}
	}
	//DynamicMusic dynamicSound(device);
	//int saberScene1 = dynamicSound.addScene(clashMutableSound);
	//int saberScene2 = dynamicSound.addScene(clashMutableSound);
	//dynamicSound.addTransition(saberScene1, saberScene2, wieldMutableSound);
	//dynamicSound.addTransition(saberScene2, saberScene1, wieldMutableSound);

	//int millis = 0;
	//while(true)
	//{
	//	dynamicSound.changeScene(saberScene1);
	//	millis = (rand() % 5000) + 5000;
	//	std::this_thread::sleep_for(std::chrono::milliseconds(millis));
	//	//dynamicSound.changeScene(saberScene2);
	//	millis = (rand() % 5000) + 5000;
	//	//std::this_thread::sleep_for(std::chrono::milliseconds(millis));
	//}

	std::this_thread::sleep_for(std::chrono::milliseconds(500000));

	return 0;
}

void loadSounds(const std::string& path, const std::string& ext, std::vector<std::shared_ptr<ISound>>& outList)
{
	std::string readpath = path;
	if(path == "")
		readpath = ".";

	WIN32_FIND_DATA entry;
	bool found_file = true;
	std::string search = readpath + "\\*";
	HANDLE dir = FindFirstFile(search.c_str(), &entry);
	if(dir == INVALID_HANDLE_VALUE)
		return;

	float azim, elev;

	while(found_file)
	{
		std::string filename = entry.cFileName;
		if(filename.length() >= ext.length() && filename.substr(filename.length() - ext.length()) == ext)
			outList.push_back(std::make_shared<File>(readpath + "/" + filename));
		found_file = FindNextFile(dir, &entry);
	}
	FindClose(dir);
	return;
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_INTERNAL_SOR_HH
#define PEGTL_INTERNAL_SOR_HH

#include "../apply_mode.hh"
#include "skip_control.hh"

#include "../analysis/generic.hh"

namespace pegtl
{
   namespace internal
   {
      template< typename ... Rules >
      struct sor
      {
         using analyze_t = analysis::generic< analysis::rule_type::SOR, Rules ... >;

         template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input, typename ... States >
         static bool match( Input & in, States && ... st )
         {
            bool result = false;
            using swallow = bool[];
            (void)swallow{ result = result || Control< Rules >::template match< A, Action, Control >( in, st ... ) ..., true };
            return result;
         }
      };

      template< typename ... Rules >
      struct skip_control< sor< Rules ... > > : std::true_type {};

   } // internal

} // pegtl

#endif
<commit_msg>Note future C++17 fold expression<commit_after>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_INTERNAL_SOR_HH
#define PEGTL_INTERNAL_SOR_HH

#include "../apply_mode.hh"
#include "skip_control.hh"

#include "../analysis/generic.hh"

namespace pegtl
{
   namespace internal
   {
      template< typename ... Rules >
      struct sor
      {
         using analyze_t = analysis::generic< analysis::rule_type::SOR, Rules ... >;

         template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input, typename ... States >
         static bool match( Input & in, States && ... st )
         {
            // C++17: return ( Control< Rules >::template match< A, Action, Control >( in, st ... ) || ... );
            bool result = false;
            using swallow = bool[];
            (void)swallow{ result = result || Control< Rules >::template match< A, Action, Control >( in, st ... ) ..., true };
            return result;
         }
      };

      template< typename ... Rules >
      struct skip_control< sor< Rules ... > > : std::true_type {};

   } // internal

} // pegtl

#endif
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "libtorrent/allocator.hpp"
#include "libtorrent/config.hpp"

#ifdef TORRENT_WINDOWS
#include <Windows.h>
#elif defined TORRENT_BEOS
#include <kernel/OS.h>
#include <stdlib.h> // malloc/free
#else
#include <stdlib.h> // valloc/free
#include <unistd.h> // _SC_PAGESIZE
#endif

namespace libtorrent
{
	int page_size()
	{
		static int s = 0;
		if (s != 0) return s;

#ifdef TORRENT_WINDOWS
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		s = si.dwPageSize;
#elif defined TORRENT_BEOS
		s = B_PAGE_SIZE;
#else
		s = sysconf(_SC_PAGESIZE);
#endif
		// assume the page size is 4 kiB if we
		// fail to query it
		if (s <= 0) s = 4096;
		return s;
	}

	char* page_aligned_allocator::malloc(const size_type bytes)
	{
#if TORRENT_USE_POSIX_MEMALIGN
		void* ret;
		if (posix_memalign(&ret, page_size(), bytes) != 0) ret = 0;
		return ret;
#elif TORRENT_USE_MEMALIGN
		return memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
		return (char*)VirtualAlloc(0, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#elif defined TORRENT_BEOS
		void* ret = 0;
		area_id id = create_area("", &ret, B_ANY_ADDRESS
			, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
		if (id < B_OK) return 0;
		return (char*)ret;
#else
		return (char*)valloc(bytes);
#endif
	}

	void page_aligned_allocator::free(char* const block)
	{
#ifdef TORRENT_WINDOWS
		VirtualFree(block, 0, MEM_RELEASE);
#elif defined TORRENT_BEOS
		area_id id = area_for(block);
		if (id < B_OK) return;
		delete_area(id);
#else
		::free(block);
#endif
	}

}

<commit_msg>memalign fix<commit_after>/*

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

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

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

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

*/

#include "libtorrent/allocator.hpp"
#include "libtorrent/config.hpp"

#ifdef TORRENT_WINDOWS
#include <Windows.h>
#elif defined TORRENT_BEOS
#include <kernel/OS.h>
#include <stdlib.h> // malloc/free
#else
#include <stdlib.h> // valloc/free
#include <unistd.h> // _SC_PAGESIZE
#endif

#if TORRENT_USE_MEMALIGN || TORRENT_USE_POSIX_MEMALIGN
#include <malloc.h> // memalign
#endif

namespace libtorrent
{
	int page_size()
	{
		static int s = 0;
		if (s != 0) return s;

#ifdef TORRENT_WINDOWS
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		s = si.dwPageSize;
#elif defined TORRENT_BEOS
		s = B_PAGE_SIZE;
#else
		s = sysconf(_SC_PAGESIZE);
#endif
		// assume the page size is 4 kiB if we
		// fail to query it
		if (s <= 0) s = 4096;
		return s;
	}

	char* page_aligned_allocator::malloc(const size_type bytes)
	{
#if TORRENT_USE_POSIX_MEMALIGN
		void* ret;
		if (posix_memalign(&ret, page_size(), bytes) != 0) ret = 0;
		return ret;
#elif TORRENT_USE_MEMALIGN
		return memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
		return (char*)VirtualAlloc(0, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#elif defined TORRENT_BEOS
		void* ret = 0;
		area_id id = create_area("", &ret, B_ANY_ADDRESS
			, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
		if (id < B_OK) return 0;
		return (char*)ret;
#else
		return (char*)valloc(bytes);
#endif
	}

	void page_aligned_allocator::free(char* const block)
	{
#ifdef TORRENT_WINDOWS
		VirtualFree(block, 0, MEM_RELEASE);
#elif defined TORRENT_BEOS
		area_id id = area_for(block);
		if (id < B_OK) return;
		delete_area(id);
#else
		::free(block);
#endif
	}

}

<|endoftext|>


<commit_before>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "PointerDetectorFilter.hpp"

#include "KmsMediaPointerDetectorFilterType_constants.h"

#include "utils/utils.hpp"
#include "utils/marshalling.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"

#define GST_CAT_DEFAULT kurento_pointer_detector_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoPointerDetectorFilter"

using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;

namespace kurento
{

void
pointerDetector_receive_message (GstBus *bus, GstMessage *message, gpointer pointerDetector)
{
  const GstStructure *st;
  gchar *windowID;
  const gchar *type;
  std::string windowIDStr, typeStr;
  PointerDetectorFilter *filter = (PointerDetectorFilter *) pointerDetector;

  if (GST_MESSAGE_SRC (message) != GST_OBJECT (filter->pointerDetector) ||
      GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
    return;

  st = gst_message_get_structure (message);
  type = gst_structure_get_name (st);

  if ( (g_strcmp0 (type, "window-out") != 0) &&
       (g_strcmp0 (type, "window-in") != 0) ) {
    GST_WARNING ("The message does not have the correct name");
    return;
  }

  if (!gst_structure_get (st, "window", G_TYPE_STRING , &windowID, NULL) ) {
    GST_WARNING ("The message does not contain the window ID");
    return;
  }

  windowIDStr = windowID;
  typeStr = type;

  g_free (windowID);

  filter->raiseEvent (typeStr, windowIDStr);

}

// FIXME: use thrift constant
PointerDetectorFilter::PointerDetectorFilter (
  MediaSet &mediaSet, std::shared_ptr<MediaPipeline> parent,
  const std::map<std::string, KmsMediaParam> &params)
  : Filter (mediaSet, parent, "POINTER_DETECTOR_FILTER_TYPE", params)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "pointerdetector", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *pointerDetector;

  g_object_get (G_OBJECT (element), "filter", &pointerDetector, NULL);

  this->pointerDetector = pointerDetector;

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (pointerDetector_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference pointerdetector because its life cycle is the same as the filter life cycle
  g_object_unref (pointerDetector);
}

PointerDetectorFilter::~PointerDetectorFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline) );
  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
PointerDetectorFilter::raiseEvent (const std::string &type, const std::string &windowID)
{
  KmsMediaEventData eventData;

  createStringEventData (eventData, windowID);

  if ( type.compare ("window-out") == 0) {
    GST_DEBUG ("Raise event. Type: %s, Window ID: %s", type.c_str(),
               windowID.c_str() );

    sendEvent (g_KmsMediaPointerDetectorFilterType_constants.EVENT_WINDOW_OUT, eventData);
  } else {
    GST_DEBUG ("Raise event. Type: %s, Window ID: %s", type.c_str(),
               windowID.c_str() );

    sendEvent (g_KmsMediaPointerDetectorFilterType_constants.EVENT_WINDOW_IN, eventData);
  }
}

PointerDetectorFilter::StaticConstructor PointerDetectorFilter::staticConstructor;

PointerDetectorFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} // kurento
<commit_msg>Change pointer detector constructor header to add thrief constant<commit_after>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "PointerDetectorFilter.hpp"

#include "KmsMediaPointerDetectorFilterType_constants.h"

#include "utils/utils.hpp"
#include "utils/marshalling.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"

#define GST_CAT_DEFAULT kurento_pointer_detector_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoPointerDetectorFilter"

using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;

namespace kurento
{

void
pointerDetector_receive_message (GstBus *bus, GstMessage *message, gpointer pointerDetector)
{
  const GstStructure *st;
  gchar *windowID;
  const gchar *type;
  std::string windowIDStr, typeStr;
  PointerDetectorFilter *filter = (PointerDetectorFilter *) pointerDetector;

  if (GST_MESSAGE_SRC (message) != GST_OBJECT (filter->pointerDetector) ||
      GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
    return;

  st = gst_message_get_structure (message);
  type = gst_structure_get_name (st);

  if ( (g_strcmp0 (type, "window-out") != 0) &&
       (g_strcmp0 (type, "window-in") != 0) ) {
    GST_WARNING ("The message does not have the correct name");
    return;
  }

  if (!gst_structure_get (st, "window", G_TYPE_STRING , &windowID, NULL) ) {
    GST_WARNING ("The message does not contain the window ID");
    return;
  }

  windowIDStr = windowID;
  typeStr = type;

  g_free (windowID);

  filter->raiseEvent (typeStr, windowIDStr);

}

PointerDetectorFilter::PointerDetectorFilter (
  MediaSet &mediaSet, std::shared_ptr<MediaPipeline> parent,
  const std::map<std::string, KmsMediaParam> &params)
  : Filter (mediaSet, parent, g_KmsMediaPointerDetectorFilterType_constants.TYPE_NAME, params)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "pointerdetector", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *pointerDetector;

  g_object_get (G_OBJECT (element), "filter", &pointerDetector, NULL);

  this->pointerDetector = pointerDetector;

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (pointerDetector_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference pointerdetector because its life cycle is the same as the filter life cycle
  g_object_unref (pointerDetector);
}

PointerDetectorFilter::~PointerDetectorFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline) );
  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
PointerDetectorFilter::raiseEvent (const std::string &type, const std::string &windowID)
{
  KmsMediaEventData eventData;

  createStringEventData (eventData, windowID);

  if ( type.compare ("window-out") == 0) {
    GST_DEBUG ("Raise event. Type: %s, Window ID: %s", type.c_str(),
               windowID.c_str() );

    sendEvent (g_KmsMediaPointerDetectorFilterType_constants.EVENT_WINDOW_OUT, eventData);
  } else {
    GST_DEBUG ("Raise event. Type: %s, Window ID: %s", type.c_str(),
               windowID.c_str() );

    sendEvent (g_KmsMediaPointerDetectorFilterType_constants.EVENT_WINDOW_IN, eventData);
  }
}

PointerDetectorFilter::StaticConstructor PointerDetectorFilter::staticConstructor;

PointerDetectorFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} // kurento
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "ConstantValue.h"

#include <boost/algorithm/string.hpp>

namespace {

std::vector<IRInstruction*> make_string_const(uint16_t dest, std::string val) {
  std::vector<IRInstruction*> res;
  IRInstruction* load = new IRInstruction(OPCODE_CONST_STRING);
  load->set_string(DexString::make_string(val));
  IRInstruction* move_result_pseudo =
      new IRInstruction(IOPCODE_MOVE_RESULT_PSEUDO_OBJECT);
  move_result_pseudo->set_dest(dest);
  res.push_back(load);
  res.push_back(move_result_pseudo);
  return res;
}

} // namespace

ConstantValue::ConstantValue(const TypeTags* type_tags,
                             const std::string kind_str,
                             const std::string val_str,
                             const uint16_t param_reg)
    : m_param_reg(param_reg) {
  if (kind_str == "I") {
    m_kind = ConstantKind::INT;
    m_int_val = std::stoll(val_str);
  } else if (kind_str == "T") {
    auto type_val = DexType::get_type(val_str.c_str());
    if (type_val != nullptr && type_tags->has_type_tag(type_val)) {
      m_kind = ConstantKind::TYPE;
      m_int_val = type_tags->get_type_tag(type_val);
      return;
    } else if (type_val == nullptr) {
      TRACE(TERA, 9, "const value: unable to find type %s\n", val_str.c_str());
    } else {
      TRACE(TERA, 9, "const value: no type tag found %s\n", val_str.c_str());
    }
    // Cannot find type or not type tag.
    m_kind = ConstantKind::INVALID;
  } else if (kind_str == "S") {
    m_kind = ConstantKind::STRING;
    m_str_val = val_str;
  } else {
    always_assert_log(false, "Unexpected kind str %s\n", kind_str.c_str());
  }
}

std::vector<ConstantValue::ConstantLoad>
ConstantValue::collect_constant_loads_in(const IRCode* code) {
  std::vector<ConstantValue::ConstantLoad> res;
  always_assert(is_valid());
  auto ii = InstructionIterable(code);
  for (auto it = ii.begin(); it != ii.end(); ++it) {
    auto insn = it->insn;
    if (is_int_value() && is_literal_const(insn->opcode())) {
      int64_t literal = insn->get_literal();
      // Special handling for type tags to avoid sign extensionon on int64_t.
      if (m_kind == ConstantKind::TYPE) {
        literal = static_cast<uint32_t>(literal);
      }
      if (is_int_value() && literal == m_int_val) {
        res.emplace_back(insn, insn->dest());
      }
    } else if (is_str_value() && insn->opcode() == OPCODE_CONST_STRING) {
      if (strcmp(insn->get_string()->c_str(), m_str_val.c_str()) == 0) {
        auto pseudo_move = std::next(it)->insn;
        always_assert(pseudo_move->opcode() ==
                      IOPCODE_MOVE_RESULT_PSEUDO_OBJECT);
        res.emplace_back(insn, pseudo_move->dest());
      }
    }
  }

  return res;
}

std::vector<IRInstruction*> ConstantValue::make_load_const(uint16_t const_reg) {
  always_assert(is_valid());

  if (is_int_value()) {
    std::vector<IRInstruction*> res;
    auto load = method_reference::make_load_const(const_reg, m_int_val);
    res.push_back(load);
    return res;
  } else {
    return make_string_const(const_reg, m_str_val);
  }
}

ConstantValues::ConstantValues(const TypeTags* type_tags,
                               const std::string kinds_str,
                               const std::string vals_str,
                               IRCode* code) {
  // Split vals_str.
  std::vector<std::string> vals_vec;
  boost::split(vals_vec, vals_str, [](char c) { return c == ':'; });
  always_assert(vals_vec.size() == kinds_str.length());

  // Build kind_to_val pairs.
  std::vector<std::pair<std::string, std::string>> kind_to_val;
  auto vals_it = vals_vec.begin();
  for (std::string::const_iterator it = kinds_str.begin();
       it != kinds_str.end();
       ++it) {
    std::string kind_str = std::string(1, *it);
    kind_to_val.emplace_back(kind_str, *vals_it);
    ++vals_it;
  }

  // Populate the const_vals set.
  for (auto& pair : kind_to_val) {
    auto param_reg = code->allocate_temp();
    ConstantValue cval(type_tags, pair.first, pair.second, param_reg);
    m_const_vals.emplace_back(cval);
    if (cval.is_invalid()) {
      m_skip_multiple_const_0 = true;
      TRACE(TERA, 9, "const value: skip multiple const 0\n");
    }
  }
}

std::vector<ConstantValues::ConstantValueLoad>
ConstantValues::collect_constant_loads(const IRCode* code) {
  std::vector<ConstantValueLoad> const_val_loads;
  for (auto& const_val : m_const_vals) {
    if (const_val.is_invalid()) {
      continue;
    }
    auto const_loads = const_val.collect_constant_loads_in(code);
    if (m_skip_multiple_const_0 && const_val.is_int_kind() &&
        const_val.get_int_value() == 0 && !const_loads.empty()) {
      const_val_loads.emplace_back(const_val, const_loads.front());
      TRACE(TERA, 9, "const value: skip const 0 loads\n");
      continue;
    }
    for (auto& load : const_loads) {
      const_val_loads.emplace_back(const_val, load);
    }
  }
  return const_val_loads;
}

std::vector<IRInstruction*> ConstantValues::make_const_loads(
    std::vector<uint16_t>& const_regs) {
  always_assert(const_regs.size() == size());
  std::vector<IRInstruction*> res;
  size_t reg_idx = 0;
  for (auto& cval : m_const_vals) {
    if (cval.is_valid()) {
      auto loads = cval.make_load_const(const_regs.at(reg_idx++));
      res.insert(res.end(), loads.begin(), loads.end());
    }
  }
  return res;
}
<commit_msg>Skip longer kind str when parsing ConstantValue<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "ConstantValue.h"

#include <boost/algorithm/string.hpp>

namespace {

std::vector<IRInstruction*> make_string_const(uint16_t dest, std::string val) {
  std::vector<IRInstruction*> res;
  IRInstruction* load = new IRInstruction(OPCODE_CONST_STRING);
  load->set_string(DexString::make_string(val));
  IRInstruction* move_result_pseudo =
      new IRInstruction(IOPCODE_MOVE_RESULT_PSEUDO_OBJECT);
  move_result_pseudo->set_dest(dest);
  res.push_back(load);
  res.push_back(move_result_pseudo);
  return res;
}

} // namespace

ConstantValue::ConstantValue(const TypeTags* type_tags,
                             const std::string kind_str,
                             const std::string val_str,
                             const uint16_t param_reg)
    : m_param_reg(param_reg) {
  if (kind_str == "I") {
    m_kind = ConstantKind::INT;
    m_int_val = std::stoll(val_str);
  } else if (kind_str == "T") {
    auto type_val = DexType::get_type(val_str.c_str());
    if (type_val != nullptr && type_tags->has_type_tag(type_val)) {
      m_kind = ConstantKind::TYPE;
      m_int_val = type_tags->get_type_tag(type_val);
      return;
    } else if (type_val == nullptr) {
      TRACE(TERA, 9, "const value: unable to find type %s\n", val_str.c_str());
    } else {
      TRACE(TERA, 9, "const value: no type tag found %s\n", val_str.c_str());
    }
    // Cannot find type or not type tag.
    m_kind = ConstantKind::INVALID;
  } else if (kind_str == "S") {
    m_kind = ConstantKind::STRING;
    m_str_val = val_str;
  } else if (kind_str.size() > 1) {
    TRACE(TERA,
          9,
          "const lift: trying to decode more than one kind %s\n",
          kind_str.c_str());
    m_kind = ConstantKind::INVALID;
  } else {
    always_assert_log(false, "Unexpected kind str %s\n", kind_str.c_str());
  }
}

std::vector<ConstantValue::ConstantLoad>
ConstantValue::collect_constant_loads_in(const IRCode* code) {
  std::vector<ConstantValue::ConstantLoad> res;
  always_assert(is_valid());
  auto ii = InstructionIterable(code);
  for (auto it = ii.begin(); it != ii.end(); ++it) {
    auto insn = it->insn;
    if (is_int_value() && is_literal_const(insn->opcode())) {
      int64_t literal = insn->get_literal();
      // Special handling for type tags to avoid sign extensionon on int64_t.
      if (m_kind == ConstantKind::TYPE) {
        literal = static_cast<uint32_t>(literal);
      }
      if (is_int_value() && literal == m_int_val) {
        res.emplace_back(insn, insn->dest());
      }
    } else if (is_str_value() && insn->opcode() == OPCODE_CONST_STRING) {
      if (strcmp(insn->get_string()->c_str(), m_str_val.c_str()) == 0) {
        auto pseudo_move = std::next(it)->insn;
        always_assert(pseudo_move->opcode() ==
                      IOPCODE_MOVE_RESULT_PSEUDO_OBJECT);
        res.emplace_back(insn, pseudo_move->dest());
      }
    }
  }

  return res;
}

std::vector<IRInstruction*> ConstantValue::make_load_const(uint16_t const_reg) {
  always_assert(is_valid());

  if (is_int_value()) {
    std::vector<IRInstruction*> res;
    auto load = method_reference::make_load_const(const_reg, m_int_val);
    res.push_back(load);
    return res;
  } else {
    return make_string_const(const_reg, m_str_val);
  }
}

ConstantValues::ConstantValues(const TypeTags* type_tags,
                               const std::string kinds_str,
                               const std::string vals_str,
                               IRCode* code) {
  // Split vals_str.
  std::vector<std::string> vals_vec;
  boost::split(vals_vec, vals_str, [](char c) { return c == ':'; });
  always_assert(vals_vec.size() == kinds_str.length());

  // Build kind_to_val pairs.
  std::vector<std::pair<std::string, std::string>> kind_to_val;
  auto vals_it = vals_vec.begin();
  for (std::string::const_iterator it = kinds_str.begin();
       it != kinds_str.end();
       ++it) {
    std::string kind_str = std::string(1, *it);
    kind_to_val.emplace_back(kind_str, *vals_it);
    ++vals_it;
  }

  // Populate the const_vals set.
  for (auto& pair : kind_to_val) {
    auto param_reg = code->allocate_temp();
    ConstantValue cval(type_tags, pair.first, pair.second, param_reg);
    m_const_vals.emplace_back(cval);
    if (cval.is_invalid()) {
      m_skip_multiple_const_0 = true;
      TRACE(TERA, 9, "const value: skip multiple const 0\n");
    }
  }
}

std::vector<ConstantValues::ConstantValueLoad>
ConstantValues::collect_constant_loads(const IRCode* code) {
  std::vector<ConstantValueLoad> const_val_loads;
  for (auto& const_val : m_const_vals) {
    if (const_val.is_invalid()) {
      continue;
    }
    auto const_loads = const_val.collect_constant_loads_in(code);
    if (m_skip_multiple_const_0 && const_val.is_int_kind() &&
        const_val.get_int_value() == 0 && !const_loads.empty()) {
      const_val_loads.emplace_back(const_val, const_loads.front());
      TRACE(TERA, 9, "const value: skip const 0 loads\n");
      continue;
    }
    for (auto& load : const_loads) {
      const_val_loads.emplace_back(const_val, load);
    }
  }
  return const_val_loads;
}

std::vector<IRInstruction*> ConstantValues::make_const_loads(
    std::vector<uint16_t>& const_regs) {
  always_assert(const_regs.size() == size());
  std::vector<IRInstruction*> res;
  size_t reg_idx = 0;
  for (auto& cval : m_const_vals) {
    if (cval.is_valid()) {
      auto loads = cval.make_load_const(const_regs.at(reg_idx++));
      res.insert(res.end(), loads.begin(), loads.end());
    }
  }
  return res;
}
<|endoftext|>


<commit_before>//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "Utility/UriParser.h"

// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;

static uint32_t g_initialize_count = 0;
static const unsigned int g_android_default_cache_size = 2048; // Fits inside 4k adb packet.

void
PlatformAndroid::Initialize ()
{
    PlatformLinux::Initialize ();

    if (g_initialize_count++ == 0)
    {
#if defined(__ANDROID__)
        PlatformSP default_platform_sp (new PlatformAndroid(true));
        default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
        Platform::SetHostPlatform (default_platform_sp);
#endif
        PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
                                       PlatformAndroid::GetPluginDescriptionStatic(false),
                                       PlatformAndroid::CreateInstance);
    }
}

void
PlatformAndroid::Terminate ()
{
    if (g_initialize_count > 0)
    {
        if (--g_initialize_count == 0)
        {
            PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
        }
    }

    PlatformLinux::Terminate ();
}

PlatformSP
PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
    if (log)
    {
        const char *arch_name;
        if (arch && arch->GetArchitectureName ())
            arch_name = arch->GetArchitectureName ();
        else
            arch_name = "<null>";

        const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";

        log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
    }

    bool create = force;
    if (create == false && arch && arch->IsValid())
    {
        const llvm::Triple &triple = arch->GetTriple();
        switch (triple.getVendor())
        {
            case llvm::Triple::PC:
                create = true;
                break;

#if defined(__ANDROID__)
            // Only accept "unknown" for the vendor if the host is android and
            // it "unknown" wasn't specified (it was just returned because it
            // was NOT specified_
            case llvm::Triple::VendorType::UnknownVendor:
                create = !arch->TripleVendorWasSpecified();
                break;
#endif
            default:
                break;
        }

        if (create)
        {
            switch (triple.getOS())
            {
                case llvm::Triple::Android:
                    break;

#if defined(__ANDROID__)
                // Only accept "unknown" for the OS if the host is android and
                // it "unknown" wasn't specified (it was just returned because it
                // was NOT specified)
                case llvm::Triple::OSType::UnknownOS:
                    create = !arch->TripleOSWasSpecified();
                    break;
#endif
                default:
                    create = false;
                    break;
            }
        }
    }

    if (create)
    {
        if (log)
            log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
        return PlatformSP(new PlatformAndroid(false));
    }

    if (log)
        log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);

    return PlatformSP();
}

PlatformAndroid::PlatformAndroid (bool is_host) :
    PlatformLinux(is_host),
    m_sdk_version(0)
{
}

PlatformAndroid::~PlatformAndroid()
{
}

ConstString
PlatformAndroid::GetPluginNameStatic (bool is_host)
{
    if (is_host)
    {
        static ConstString g_host_name(Platform::GetHostPlatformName ());
        return g_host_name;
    }
    else
    {
        static ConstString g_remote_name("remote-android");
        return g_remote_name;
    }
}

const char *
PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
{
    if (is_host)
        return "Local Android user platform plug-in.";
    else
        return "Remote Android user platform plug-in.";
}

ConstString
PlatformAndroid::GetPluginName()
{
    return GetPluginNameStatic(IsHost());
}

Error
PlatformAndroid::ConnectRemote(Args& args)
{
    m_device_id.clear();

    if (IsHost())
    {
        return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
    }

    if (!m_remote_platform_sp)
        m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());

    int port;
    std::string scheme, host, path;
    const char *url = args.GetArgumentAtIndex(0);
    if (!url)
        return Error("URL is null.");
    if (!UriParser::Parse(url, scheme, host, port, path))
        return Error("Invalid URL: %s", url);
    if (host != "localhost")
        m_device_id = host;

    auto error = PlatformLinux::ConnectRemote(args);
    if (error.Success())
    {
        AdbClient adb;
        error = AdbClient::CreateByDeviceID(m_device_id, adb);
        if (error.Fail())
            return error;

        m_device_id = adb.GetDeviceID();
    }
    return error;
}

Error
PlatformAndroid::GetFile (const FileSpec& source,
                          const FileSpec& destination)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::GetFile(source, destination);

    FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (source_spec.IsRelative())
        source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false));

    Error error;
    auto sync_service = GetSyncService (error);
    if (error.Fail ())
        return error;

    uint32_t mode = 0, size = 0, mtime = 0;
    error = sync_service->Stat(source_spec, mode, size, mtime);
    if (error.Fail())
        return error;

    if (mode != 0)
        return sync_service->PullFile(source_spec, destination);

    auto source_file = source_spec.GetCString(false);

    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
    if (log)
        log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file);

    if (strchr(source_file, '\'') != nullptr)
        return Error("Doesn't support single-quotes in filenames");

    // mode == 0 can signify that adbd cannot access the file
    // due security constraints - try "cat ..." as a fallback.
    AdbClient adb(m_device_id);

    char cmd[PATH_MAX];
    snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);

    return adb.ShellToFile(cmd, 60000 /* ms */, destination);
}

Error
PlatformAndroid::PutFile (const FileSpec& source,
                          const FileSpec& destination,
                          uint32_t uid,
                          uint32_t gid)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::PutFile (source, destination, uid, gid);

    FileSpec destination_spec (destination.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (destination_spec.IsRelative())
        destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false));

    // TODO: Set correct uid and gid on remote file.
    Error error;
    auto sync_service = GetSyncService (error);
    if (error.Fail ())
        return error;
    return sync_service->PushFile(source, destination_spec);
}

const char *
PlatformAndroid::GetCacheHostname ()
{
    return m_device_id.c_str ();
}

Error
PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec,
                                      const uint64_t src_offset,
                                      const uint64_t src_size,
                                      const FileSpec &dst_file_spec)
{
    if (src_offset != 0)
        return Error ("Invalid offset - %" PRIu64, src_offset);

    return GetFile (src_file_spec, dst_file_spec);
}

Error
PlatformAndroid::DisconnectRemote()
{
    Error error = PlatformLinux::DisconnectRemote();
    if (error.Success())
    {
        m_device_id.clear();
        m_sdk_version = 0;
    }
    return error;
}

uint32_t
PlatformAndroid::GetDefaultMemoryCacheLineSize()
{
    return g_android_default_cache_size;
}

uint32_t
PlatformAndroid::GetSdkVersion()
{
    if (!IsConnected())
        return 0;

    if (m_sdk_version != 0)
        return m_sdk_version;

    std::string version_string;
    AdbClient adb(m_device_id);
    Error error = adb.Shell("getprop ro.build.version.sdk", 5000 /* ms */, &version_string);
    version_string = llvm::StringRef(version_string).trim().str();

    if (error.Fail() || version_string.empty())
    {
        Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM);
        if (log)
            log->Printf("Get SDK version failed. (error: %s, output: %s)",
                        error.AsCString(), version_string.c_str());
        return 0;
    }

    m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
    return m_sdk_version;
}

Error
PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp,
                                     const FileSpec& dst_file_spec)
{
    // For oat file we can try to fetch additional debug info from the device
    ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
    if (extension != ConstString("oat") && extension != ConstString("odex"))
        return Error("Symbol file downloading only supported for oat and odex files");

    // If we have no information about the platform file we can't execute oatdump
    if (!module_sp->GetPlatformFileSpec())
        return Error("No platform file specified");

    // Symbolizer isn't available before SDK version 23
    if (GetSdkVersion() < 23)
        return Error("Symbol file generation only supported on SDK 23+");

    // If we already have symtab then we don't have to try and generate one
    if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr)
        return Error("Symtab already available in the module");

    AdbClient adb(m_device_id);
    std::string tmpdir;
    Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", 5000 /* ms */, &tmpdir);
    if (error.Fail() || tmpdir.empty())
        return Error("Failed to generate temporary directory on the device (%s)", error.AsCString());
    tmpdir = llvm::StringRef(tmpdir).trim().str();

    // Create file remover for the temporary directory created on the device
    std::unique_ptr<std::string, std::function<void(std::string*)>> tmpdir_remover(
        &tmpdir,
        [this, &adb](std::string* s) {
            StreamString command;
            command.Printf("rm -rf %s", s->c_str());
            Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr);

            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
            if (error.Fail())
                log->Printf("Failed to remove temp directory: %s", error.AsCString());
        }
    );

    FileSpec symfile_platform_filespec(tmpdir.c_str(), false);
    symfile_platform_filespec.AppendPathComponent("symbolized.oat");

    // Execute oatdump on the remote device to generate a file with symtab
    StreamString command;
    command.Printf("oatdump --symbolize=%s --output=%s",
                   module_sp->GetPlatformFileSpec().GetCString(false),
                   symfile_platform_filespec.GetCString(false));
    error = adb.Shell(command.GetData(), 60000 /* ms */, nullptr);
    if (error.Fail())
        return Error("Oatdump failed: %s", error.AsCString());

    // Download the symbolfile from the remote device
    return GetFile(symfile_platform_filespec, dst_file_spec);
}

bool
PlatformAndroid::GetRemoteOSVersion ()
{
    m_major_os_version = GetSdkVersion();
    m_minor_os_version = 0;
    m_update_os_version = 0;
    return m_major_os_version != 0;
}

const char*
PlatformAndroid::GetLibdlFunctionDeclarations() const
{
    return R"(
              extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
              extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
              extern "C" int   dlclose(void*) asm("__dl_dlclose");
              extern "C" char* dlerror(void) asm("__dl_dlerror");
             )";
}

AdbClient::SyncService*
PlatformAndroid::GetSyncService (Error &error)
{
    if (m_adb_sync_svc && m_adb_sync_svc->IsConnected ())
        return m_adb_sync_svc.get ();

    AdbClient adb (m_device_id);
    m_adb_sync_svc = adb.GetSyncService (error);
    return (error.Success ()) ? m_adb_sync_svc.get () : nullptr;
}

<commit_msg>Add check for non-null log instance in PlatformAndroid.<commit_after>//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "Utility/UriParser.h"

// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;

static uint32_t g_initialize_count = 0;
static const unsigned int g_android_default_cache_size = 2048; // Fits inside 4k adb packet.

void
PlatformAndroid::Initialize ()
{
    PlatformLinux::Initialize ();

    if (g_initialize_count++ == 0)
    {
#if defined(__ANDROID__)
        PlatformSP default_platform_sp (new PlatformAndroid(true));
        default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
        Platform::SetHostPlatform (default_platform_sp);
#endif
        PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
                                       PlatformAndroid::GetPluginDescriptionStatic(false),
                                       PlatformAndroid::CreateInstance);
    }
}

void
PlatformAndroid::Terminate ()
{
    if (g_initialize_count > 0)
    {
        if (--g_initialize_count == 0)
        {
            PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
        }
    }

    PlatformLinux::Terminate ();
}

PlatformSP
PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
    if (log)
    {
        const char *arch_name;
        if (arch && arch->GetArchitectureName ())
            arch_name = arch->GetArchitectureName ();
        else
            arch_name = "<null>";

        const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";

        log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
    }

    bool create = force;
    if (create == false && arch && arch->IsValid())
    {
        const llvm::Triple &triple = arch->GetTriple();
        switch (triple.getVendor())
        {
            case llvm::Triple::PC:
                create = true;
                break;

#if defined(__ANDROID__)
            // Only accept "unknown" for the vendor if the host is android and
            // it "unknown" wasn't specified (it was just returned because it
            // was NOT specified_
            case llvm::Triple::VendorType::UnknownVendor:
                create = !arch->TripleVendorWasSpecified();
                break;
#endif
            default:
                break;
        }

        if (create)
        {
            switch (triple.getOS())
            {
                case llvm::Triple::Android:
                    break;

#if defined(__ANDROID__)
                // Only accept "unknown" for the OS if the host is android and
                // it "unknown" wasn't specified (it was just returned because it
                // was NOT specified)
                case llvm::Triple::OSType::UnknownOS:
                    create = !arch->TripleOSWasSpecified();
                    break;
#endif
                default:
                    create = false;
                    break;
            }
        }
    }

    if (create)
    {
        if (log)
            log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
        return PlatformSP(new PlatformAndroid(false));
    }

    if (log)
        log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);

    return PlatformSP();
}

PlatformAndroid::PlatformAndroid (bool is_host) :
    PlatformLinux(is_host),
    m_sdk_version(0)
{
}

PlatformAndroid::~PlatformAndroid()
{
}

ConstString
PlatformAndroid::GetPluginNameStatic (bool is_host)
{
    if (is_host)
    {
        static ConstString g_host_name(Platform::GetHostPlatformName ());
        return g_host_name;
    }
    else
    {
        static ConstString g_remote_name("remote-android");
        return g_remote_name;
    }
}

const char *
PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
{
    if (is_host)
        return "Local Android user platform plug-in.";
    else
        return "Remote Android user platform plug-in.";
}

ConstString
PlatformAndroid::GetPluginName()
{
    return GetPluginNameStatic(IsHost());
}

Error
PlatformAndroid::ConnectRemote(Args& args)
{
    m_device_id.clear();

    if (IsHost())
    {
        return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
    }

    if (!m_remote_platform_sp)
        m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());

    int port;
    std::string scheme, host, path;
    const char *url = args.GetArgumentAtIndex(0);
    if (!url)
        return Error("URL is null.");
    if (!UriParser::Parse(url, scheme, host, port, path))
        return Error("Invalid URL: %s", url);
    if (host != "localhost")
        m_device_id = host;

    auto error = PlatformLinux::ConnectRemote(args);
    if (error.Success())
    {
        AdbClient adb;
        error = AdbClient::CreateByDeviceID(m_device_id, adb);
        if (error.Fail())
            return error;

        m_device_id = adb.GetDeviceID();
    }
    return error;
}

Error
PlatformAndroid::GetFile (const FileSpec& source,
                          const FileSpec& destination)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::GetFile(source, destination);

    FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (source_spec.IsRelative())
        source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false));

    Error error;
    auto sync_service = GetSyncService (error);
    if (error.Fail ())
        return error;

    uint32_t mode = 0, size = 0, mtime = 0;
    error = sync_service->Stat(source_spec, mode, size, mtime);
    if (error.Fail())
        return error;

    if (mode != 0)
        return sync_service->PullFile(source_spec, destination);

    auto source_file = source_spec.GetCString(false);

    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
    if (log)
        log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file);

    if (strchr(source_file, '\'') != nullptr)
        return Error("Doesn't support single-quotes in filenames");

    // mode == 0 can signify that adbd cannot access the file
    // due security constraints - try "cat ..." as a fallback.
    AdbClient adb(m_device_id);

    char cmd[PATH_MAX];
    snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);

    return adb.ShellToFile(cmd, 60000 /* ms */, destination);
}

Error
PlatformAndroid::PutFile (const FileSpec& source,
                          const FileSpec& destination,
                          uint32_t uid,
                          uint32_t gid)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::PutFile (source, destination, uid, gid);

    FileSpec destination_spec (destination.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (destination_spec.IsRelative())
        destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false));

    // TODO: Set correct uid and gid on remote file.
    Error error;
    auto sync_service = GetSyncService (error);
    if (error.Fail ())
        return error;
    return sync_service->PushFile(source, destination_spec);
}

const char *
PlatformAndroid::GetCacheHostname ()
{
    return m_device_id.c_str ();
}

Error
PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec,
                                      const uint64_t src_offset,
                                      const uint64_t src_size,
                                      const FileSpec &dst_file_spec)
{
    if (src_offset != 0)
        return Error ("Invalid offset - %" PRIu64, src_offset);

    return GetFile (src_file_spec, dst_file_spec);
}

Error
PlatformAndroid::DisconnectRemote()
{
    Error error = PlatformLinux::DisconnectRemote();
    if (error.Success())
    {
        m_device_id.clear();
        m_sdk_version = 0;
    }
    return error;
}

uint32_t
PlatformAndroid::GetDefaultMemoryCacheLineSize()
{
    return g_android_default_cache_size;
}

uint32_t
PlatformAndroid::GetSdkVersion()
{
    if (!IsConnected())
        return 0;

    if (m_sdk_version != 0)
        return m_sdk_version;

    std::string version_string;
    AdbClient adb(m_device_id);
    Error error = adb.Shell("getprop ro.build.version.sdk", 5000 /* ms */, &version_string);
    version_string = llvm::StringRef(version_string).trim().str();

    if (error.Fail() || version_string.empty())
    {
        Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM);
        if (log)
            log->Printf("Get SDK version failed. (error: %s, output: %s)",
                        error.AsCString(), version_string.c_str());
        return 0;
    }

    m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
    return m_sdk_version;
}

Error
PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp,
                                     const FileSpec& dst_file_spec)
{
    // For oat file we can try to fetch additional debug info from the device
    ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
    if (extension != ConstString("oat") && extension != ConstString("odex"))
        return Error("Symbol file downloading only supported for oat and odex files");

    // If we have no information about the platform file we can't execute oatdump
    if (!module_sp->GetPlatformFileSpec())
        return Error("No platform file specified");

    // Symbolizer isn't available before SDK version 23
    if (GetSdkVersion() < 23)
        return Error("Symbol file generation only supported on SDK 23+");

    // If we already have symtab then we don't have to try and generate one
    if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr)
        return Error("Symtab already available in the module");

    AdbClient adb(m_device_id);
    std::string tmpdir;
    Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", 5000 /* ms */, &tmpdir);
    if (error.Fail() || tmpdir.empty())
        return Error("Failed to generate temporary directory on the device (%s)", error.AsCString());
    tmpdir = llvm::StringRef(tmpdir).trim().str();

    // Create file remover for the temporary directory created on the device
    std::unique_ptr<std::string, std::function<void(std::string*)>> tmpdir_remover(
        &tmpdir,
        [this, &adb](std::string* s) {
            StreamString command;
            command.Printf("rm -rf %s", s->c_str());
            Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr);

            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
            if (log && error.Fail())
                log->Printf("Failed to remove temp directory: %s", error.AsCString());
        }
    );

    FileSpec symfile_platform_filespec(tmpdir.c_str(), false);
    symfile_platform_filespec.AppendPathComponent("symbolized.oat");

    // Execute oatdump on the remote device to generate a file with symtab
    StreamString command;
    command.Printf("oatdump --symbolize=%s --output=%s",
                   module_sp->GetPlatformFileSpec().GetCString(false),
                   symfile_platform_filespec.GetCString(false));
    error = adb.Shell(command.GetData(), 60000 /* ms */, nullptr);
    if (error.Fail())
        return Error("Oatdump failed: %s", error.AsCString());

    // Download the symbolfile from the remote device
    return GetFile(symfile_platform_filespec, dst_file_spec);
}

bool
PlatformAndroid::GetRemoteOSVersion ()
{
    m_major_os_version = GetSdkVersion();
    m_minor_os_version = 0;
    m_update_os_version = 0;
    return m_major_os_version != 0;
}

const char*
PlatformAndroid::GetLibdlFunctionDeclarations() const
{
    return R"(
              extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
              extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
              extern "C" int   dlclose(void*) asm("__dl_dlclose");
              extern "C" char* dlerror(void) asm("__dl_dlerror");
             )";
}

AdbClient::SyncService*
PlatformAndroid::GetSyncService (Error &error)
{
    if (m_adb_sync_svc && m_adb_sync_svc->IsConnected ())
        return m_adb_sync_svc.get ();

    AdbClient adb (m_device_id);
    m_adb_sync_svc = adb.GetSyncService (error);
    return (error.Success ()) ? m_adb_sync_svc.get () : nullptr;
}

<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <ros/forwards.h>
#include <ros/single_subscriber_publisher.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <visualization_msgs/Marker.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <cv_bridge/cv_bridge.h>

#include <src/TagDetector.h>
#include <src/TagDetection.h>
#include <src/TagFamily.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <visualization_msgs/MarkerArray.h>
#include "yaml-cpp/yaml.h"
#include <sstream>
#include <fstream>

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/make_shared.hpp>

#include "apriltags.h"

using namespace std;

// Functions

double GetTagSize(int tag_id)
{
    boost::unordered_map<size_t, double>::iterator tag_sizes_it =
        tag_sizes_.find(tag_id);
    if(tag_sizes_it != tag_sizes_.end()) {
        return tag_sizes_it->second;
    } else {
        return default_tag_size_;
    }
}

Eigen::Matrix4d GetDetectionTransform(TagDetection detection)
{
    double tag_size = GetTagSize(detection.id);

    std::vector<cv::Point3f> object_pts;
    std::vector<cv::Point2f> image_pts;
    double tag_radius = tag_size/2.;

    object_pts.push_back(cv::Point3f(-tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius,  tag_radius, 0));
    object_pts.push_back(cv::Point3f(-tag_radius,  tag_radius, 0));

    image_pts.push_back(detection.p[0]);
    image_pts.push_back(detection.p[1]);
    image_pts.push_back(detection.p[2]);
    image_pts.push_back(detection.p[3]);

    cv::Matx33f intrinsics(camera_info_.K[0], 0, camera_info_.K[2],
                           0, camera_info_.K[4], camera_info_.K[5],
                           0, 0, 1);

    cv::Mat rvec, tvec;
    cv::Vec4f dist_param(0,0,0,0);
    cv::solvePnP(object_pts, image_pts, intrinsics, dist_param,
            rvec, tvec);
    cv::Matx33d r;
    cv::Rodrigues(rvec, r);
    Eigen::Matrix3d rot;
    rot << r(0,0), r(0,1), r(0,2),
           r(1,0), r(1,1), r(1,2),
           r(2,0), r(2,1), r(2,2);

    Eigen::Matrix4d T;
    T.topLeftCorner(3,3) = rot;
    T.col(3).head(3) <<
            tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2);
    T.row(3) << 0,0,0,1;

    return T;
}

// Callback for camera info
void InfoCallback(const sensor_msgs::CameraInfoConstPtr& camera_info)
{
    camera_info_ = (*camera_info);
    has_camera_info_ = true;
}

// Callback for image data
void ImageCallback(const sensor_msgs::ImageConstPtr& msg )
{
    if(!has_camera_info_){
        ROS_WARN("No Camera Info Received Yet");
        return;
    }

    // Get the image
    cv_bridge::CvImagePtr subscribed_ptr;
    try
    {
        subscribed_ptr = cv_bridge::toCvCopy(msg, "mono8");
    }
    catch(cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return;
    }

    cv::Mat subscribed_gray = subscribed_ptr->image;
    cv::Mat tmp;
    cv::Point2d opticalCenter(0.5*subscribed_gray.rows,
                              0.5*subscribed_gray.cols);
    TagDetectionArray detections;
    detector_->process(subscribed_gray, opticalCenter, detections);
    visualization_msgs::MarkerArray marker_transforms;

    cout << tag_size << endl;

    if(viewer_)
    {
        subscribed_gray = family_->superimposeDetections(subscribed_gray,
                                                         detections);
    }
    for(unsigned int i = 0; i < detections.size(); ++i)
    {
        Eigen::Matrix4d pose = GetDetectionTransform(detections[i]);

        // Get this info from earlier code, don't extract it again
        Eigen::Matrix3d R = pose.block<3,3>(0,0);
        Eigen::Quaternion<double> q(R);

    	double tag_size = GetTagSize(detections[i].id);
        cout << tag_size << endl;

        visualization_msgs::Marker marker_transform;
        marker_transform.header.frame_id = frame_;
        marker_transform.header.stamp = ros::Time::now();
        stringstream convert;
        convert << "tag" << detections[i].id;
        marker_transform.ns = convert.str().c_str();
        marker_transform.id = detections[i].id;
        if(display_type_ == "ARROW"){
            marker_transform.type = visualization_msgs::Marker::ARROW;
            marker_transform.scale.x = tag_size;
            marker_transform.scale.y = tag_size*10;
            marker_transform.scale.z = tag_size*0.5;
        }
        else if(display_type_ == "CUBE"){
            marker_transform.type = visualization_msgs::Marker::CUBE;
            marker_transform.scale.x = tag_size;
            marker_transform.scale.y = tag_size;
            marker_transform.scale.z = 0.01 * tag_size;
        }
        marker_transform.action = visualization_msgs::Marker::ADD;
        marker_transform.pose.position.x = pose(0,3);
        marker_transform.pose.position.y = pose(1,3);
        marker_transform.pose.position.z = pose(2,3);
        marker_transform.pose.orientation.x = q.x();
        marker_transform.pose.orientation.y = q.y();
        marker_transform.pose.orientation.z = q.z();
        marker_transform.pose.orientation.w = q.w();

        marker_transform.color.r = 1.0;
        marker_transform.color.g = 0.0;
        marker_transform.color.b = 1.0;
        marker_transform.color.a = 1.0;
        marker_transforms.markers.push_back(marker_transform);
    }
    marker_publisher_.publish(marker_transforms);

    if(viewer_)
    {
        cv::imshow("AprilTags", subscribed_gray);
    }
}

void ConnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Subscription detected! (%d subscribers)", subscribers);

    if(subscribers && !running_)
    {
        ROS_DEBUG("New Subscribers, Connecting to Input Image Topic.");
        ros::TransportHints ros_transport_hints(ros::TransportHints().tcpNoDelay());
        image_transport::TransportHints image_transport_hint(image_transport::TransportHints(
                                "raw", ros_transport_hints, (*node_),
                                "image_transport"));

        image_subscriber = (*image_).subscribe(
                DEFAULT_IMAGE_TOPIC, 1, &ImageCallback,
                image_transport_hint);
        info_subscriber = (*node_).subscribe(
                DEFAULT_CAMERA_INFO_TOPIC, 10, &InfoCallback);
        running_ = true;
    }
}

void DisconnectHandler()
{
}

void DisconnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Unsubscription detected! (%d subscribers)", subscribers);

    if(!subscribers && running_)
    {
        ROS_DEBUG("No Subscribers, Disconnecting from Input Image Topic.");
		image_subscriber.shutdown();
		info_subscriber.shutdown();
		running_ = false;
    }
}

void GetParameterValues()
{
    // Load node-wide configuration values.
    node_->param("viewer", viewer_, 0);
    node_->param("tag_family", tag_family_name_, DEFAULT_TAG_FAMILY);
    node_->param("default_tag_size", default_tag_size_, DEFAULT_TAG_SIZE);
    node_->param("tf_frame", frame_, DEFAULT_TF_FRAME);
    node_->param("display_type", display_type_, DEFAULT_DISPLAY_TYPE);

    // Load tag specific configuration values.
    XmlRpc::XmlRpcValue tag_data;
    node_->param("tag_data", tag_data, tag_data);

    // Iterate through each tag in the configuration.
    XmlRpc::XmlRpcValue::ValueStruct::iterator it;
    for (it = tag_data.begin(); it != tag_data.end(); ++it)
    {
        // Retrieve the settings for the next tag.
        int tag_id = boost::lexical_cast<int>(it->first);
        XmlRpc::XmlRpcValue tag_values = it->second;

        // Load all the settings for this tag.
        if (tag_values.hasMember("size"))
        {
            tag_sizes_[tag_id] = static_cast<double>(tag_values["size"]);
            ROS_DEBUG("Setting tag%d to size %f m.", tag_id, tag_sizes_[tag_id]);
        }
    }
}

void SetupPublisher()
{
    ros::SubscriberStatusCallback connect_callback = &ConnectCallback;
    ros::SubscriberStatusCallback disconnect_callback = &DisconnectCallback;

    // Publisher
    marker_publisher_ = node_->advertise<visualization_msgs::MarkerArray>(
            DEFAULT_MARKER_TOPIC, 1, connect_callback,
            disconnect_callback);
}

void InitializeTags()
{
    tag_params.newQuadAlgorithm = 1;
    family_ = new TagFamily(tag_family_name_);
    detector_ = new TagDetector(*family_, tag_params);
}

void InitializeROSNode(int argc, char **argv)
{
    ros::init(argc, argv, "apriltags");
    node_ =  boost::make_shared<ros::NodeHandle>("~");
    image_ = boost::make_shared<image_transport::ImageTransport>(*node_);
}

int main(int argc, char **argv)
{
    InitializeROSNode(argc,argv);
    GetParameterValues();
    SetupPublisher();
    InitializeTags();

    if(viewer_){
        cvNamedWindow("AprilTags");
        cvStartWindowThread();
    }

    ROS_INFO("AprilTags node started.");
    running_ = false;
    has_camera_info_ = false;
    ros::spin();
    ROS_INFO("AprilTags node stopped.");

    //Destroying Stuff
    cvDestroyWindow("AprilTags");
    delete detector_;
    delete family_;

    return EXIT_SUCCESS;
}
<commit_msg>spitting out tag size for debugging temporarily<commit_after>#include <ros/ros.h>
#include <ros/forwards.h>
#include <ros/single_subscriber_publisher.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <visualization_msgs/Marker.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <cv_bridge/cv_bridge.h>

#include <src/TagDetector.h>
#include <src/TagDetection.h>
#include <src/TagFamily.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <visualization_msgs/MarkerArray.h>
#include "yaml-cpp/yaml.h"
#include <sstream>
#include <fstream>

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/make_shared.hpp>

#include "apriltags.h"

using namespace std;

// Functions

double GetTagSize(int tag_id)
{
    boost::unordered_map<size_t, double>::iterator tag_sizes_it =
        tag_sizes_.find(tag_id);
    if(tag_sizes_it != tag_sizes_.end()) {
        return tag_sizes_it->second;
    } else {
        return default_tag_size_;
    }
}

Eigen::Matrix4d GetDetectionTransform(TagDetection detection)
{
    double tag_size = GetTagSize(detection.id);

    std::vector<cv::Point3f> object_pts;
    std::vector<cv::Point2f> image_pts;
    double tag_radius = tag_size/2.;

    object_pts.push_back(cv::Point3f(-tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius,  tag_radius, 0));
    object_pts.push_back(cv::Point3f(-tag_radius,  tag_radius, 0));

    image_pts.push_back(detection.p[0]);
    image_pts.push_back(detection.p[1]);
    image_pts.push_back(detection.p[2]);
    image_pts.push_back(detection.p[3]);

    cv::Matx33f intrinsics(camera_info_.K[0], 0, camera_info_.K[2],
                           0, camera_info_.K[4], camera_info_.K[5],
                           0, 0, 1);

    cv::Mat rvec, tvec;
    cv::Vec4f dist_param(0,0,0,0);
    cv::solvePnP(object_pts, image_pts, intrinsics, dist_param,
            rvec, tvec);
    cv::Matx33d r;
    cv::Rodrigues(rvec, r);
    Eigen::Matrix3d rot;
    rot << r(0,0), r(0,1), r(0,2),
           r(1,0), r(1,1), r(1,2),
           r(2,0), r(2,1), r(2,2);

    Eigen::Matrix4d T;
    T.topLeftCorner(3,3) = rot;
    T.col(3).head(3) <<
            tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2);
    T.row(3) << 0,0,0,1;

    return T;
}

// Callback for camera info
void InfoCallback(const sensor_msgs::CameraInfoConstPtr& camera_info)
{
    camera_info_ = (*camera_info);
    has_camera_info_ = true;
}

// Callback for image data
void ImageCallback(const sensor_msgs::ImageConstPtr& msg )
{
    if(!has_camera_info_){
        ROS_WARN("No Camera Info Received Yet");
        return;
    }

    // Get the image
    cv_bridge::CvImagePtr subscribed_ptr;
    try
    {
        subscribed_ptr = cv_bridge::toCvCopy(msg, "mono8");
    }
    catch(cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return;
    }

    cv::Mat subscribed_gray = subscribed_ptr->image;
    cv::Mat tmp;
    cv::Point2d opticalCenter(0.5*subscribed_gray.rows,
                              0.5*subscribed_gray.cols);
    TagDetectionArray detections;
    detector_->process(subscribed_gray, opticalCenter, detections);
    visualization_msgs::MarkerArray marker_transforms;

    if(viewer_)
    {
        subscribed_gray = family_->superimposeDetections(subscribed_gray,
                                                         detections);
    }
    for(unsigned int i = 0; i < detections.size(); ++i)
    {
        Eigen::Matrix4d pose = GetDetectionTransform(detections[i]);

        // Get this info from earlier code, don't extract it again
        Eigen::Matrix3d R = pose.block<3,3>(0,0);
        Eigen::Quaternion<double> q(R);

    	double tag_size = GetTagSize(detections[i].id);
        cout << tag_size << endl;

        visualization_msgs::Marker marker_transform;
        marker_transform.header.frame_id = frame_;
        marker_transform.header.stamp = ros::Time::now();
        stringstream convert;
        convert << "tag" << detections[i].id;
        marker_transform.ns = convert.str().c_str();
        marker_transform.id = detections[i].id;
        if(display_type_ == "ARROW"){
            marker_transform.type = visualization_msgs::Marker::ARROW;
            marker_transform.scale.x = tag_size;
            marker_transform.scale.y = tag_size*10;
            marker_transform.scale.z = tag_size*0.5;
        }
        else if(display_type_ == "CUBE"){
            marker_transform.type = visualization_msgs::Marker::CUBE;
            marker_transform.scale.x = tag_size;
            marker_transform.scale.y = tag_size;
            marker_transform.scale.z = 0.01 * tag_size;
        }
        marker_transform.action = visualization_msgs::Marker::ADD;
        marker_transform.pose.position.x = pose(0,3);
        marker_transform.pose.position.y = pose(1,3);
        marker_transform.pose.position.z = pose(2,3);
        marker_transform.pose.orientation.x = q.x();
        marker_transform.pose.orientation.y = q.y();
        marker_transform.pose.orientation.z = q.z();
        marker_transform.pose.orientation.w = q.w();

        marker_transform.color.r = 1.0;
        marker_transform.color.g = 0.0;
        marker_transform.color.b = 1.0;
        marker_transform.color.a = 1.0;
        marker_transforms.markers.push_back(marker_transform);
    }
    marker_publisher_.publish(marker_transforms);

    if(viewer_)
    {
        cv::imshow("AprilTags", subscribed_gray);
    }
}

void ConnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Subscription detected! (%d subscribers)", subscribers);

    if(subscribers && !running_)
    {
        ROS_DEBUG("New Subscribers, Connecting to Input Image Topic.");
        ros::TransportHints ros_transport_hints(ros::TransportHints().tcpNoDelay());
        image_transport::TransportHints image_transport_hint(image_transport::TransportHints(
                                "raw", ros_transport_hints, (*node_),
                                "image_transport"));

        image_subscriber = (*image_).subscribe(
                DEFAULT_IMAGE_TOPIC, 1, &ImageCallback,
                image_transport_hint);
        info_subscriber = (*node_).subscribe(
                DEFAULT_CAMERA_INFO_TOPIC, 10, &InfoCallback);
        running_ = true;
    }
}

void DisconnectHandler()
{
}

void DisconnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Unsubscription detected! (%d subscribers)", subscribers);

    if(!subscribers && running_)
    {
        ROS_DEBUG("No Subscribers, Disconnecting from Input Image Topic.");
		image_subscriber.shutdown();
		info_subscriber.shutdown();
		running_ = false;
    }
}

void GetParameterValues()
{
    // Load node-wide configuration values.
    node_->param("viewer", viewer_, 0);
    node_->param("tag_family", tag_family_name_, DEFAULT_TAG_FAMILY);
    node_->param("default_tag_size", default_tag_size_, DEFAULT_TAG_SIZE);
    node_->param("tf_frame", frame_, DEFAULT_TF_FRAME);
    node_->param("display_type", display_type_, DEFAULT_DISPLAY_TYPE);

    // Load tag specific configuration values.
    XmlRpc::XmlRpcValue tag_data;
    node_->param("tag_data", tag_data, tag_data);

    // Iterate through each tag in the configuration.
    XmlRpc::XmlRpcValue::ValueStruct::iterator it;
    for (it = tag_data.begin(); it != tag_data.end(); ++it)
    {
        // Retrieve the settings for the next tag.
        int tag_id = boost::lexical_cast<int>(it->first);
        XmlRpc::XmlRpcValue tag_values = it->second;

        // Load all the settings for this tag.
        if (tag_values.hasMember("size"))
        {
            tag_sizes_[tag_id] = static_cast<double>(tag_values["size"]);
            ROS_DEBUG("Setting tag%d to size %f m.", tag_id, tag_sizes_[tag_id]);
        }
    }
}

void SetupPublisher()
{
    ros::SubscriberStatusCallback connect_callback = &ConnectCallback;
    ros::SubscriberStatusCallback disconnect_callback = &DisconnectCallback;

    // Publisher
    marker_publisher_ = node_->advertise<visualization_msgs::MarkerArray>(
            DEFAULT_MARKER_TOPIC, 1, connect_callback,
            disconnect_callback);
}

void InitializeTags()
{
    tag_params.newQuadAlgorithm = 1;
    family_ = new TagFamily(tag_family_name_);
    detector_ = new TagDetector(*family_, tag_params);
}

void InitializeROSNode(int argc, char **argv)
{
    ros::init(argc, argv, "apriltags");
    node_ =  boost::make_shared<ros::NodeHandle>("~");
    image_ = boost::make_shared<image_transport::ImageTransport>(*node_);
}

int main(int argc, char **argv)
{
    InitializeROSNode(argc,argv);
    GetParameterValues();
    SetupPublisher();
    InitializeTags();

    if(viewer_){
        cvNamedWindow("AprilTags");
        cvStartWindowThread();
    }

    ROS_INFO("AprilTags node started.");
    running_ = false;
    has_camera_info_ = false;
    ros::spin();
    ROS_INFO("AprilTags node stopped.");

    //Destroying Stuff
    cvDestroyWindow("AprilTags");
    delete detector_;
    delete family_;

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2012 Stuart Walsh

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

#include "stdinc.h"
#include "baseclient.h"
#include "connection.h"
#include "server.h"
#include "system.h"

unordered_map<string, ClientPtr> BaseClient::names;

BaseClient::BaseClient() : level(Unregistered)
{
  Logging::debug << "Created Client: " << this << Logging::endl;
}

BaseClient::~BaseClient()
{
  Logging::debug << "Destroyed Client: " << this << Logging::endl;
}

void BaseClient::send(string message)
{
  if (message.length() >= 510)
    message.resize(510);

  message.append("\r\n");

  connection->send(message);
}

string BaseClient::str() const
{
  if(name.empty())
    return "*";
  else
    return name;
}

bool BaseClient::is_registered() const
{
  return level >= Registered;
}

void BaseClient::clear_connection()
{
  connection.reset();
}

string BaseClient::get_name() const
{
  return name;
}

string BaseClient::get_host() const
{
  return host;
}

void BaseClient::set_name(const string _name)
{
  name = _name;
}

void BaseClient::set_registered()
{
  level = Registered;
}

void BaseClient::set_connection(const ConnectionPtr conn)
{
  connection = conn;
  host = connection->get_host();
}

//  Statics

void BaseClient::init()
{
  ClientPtr me = ClientPtr(new Server);
  shared_ptr<Server> me_ptr = dynamic_pointer_cast<Server>(me);

  me->set_name(System::get_server_name());
  me_ptr->set_info(System::get_server_info());

  Server::set_me(me);
}

void BaseClient::add_name(const ClientPtr client)
{
  names[client->name] = client;
}

ClientPtr BaseClient::find_by_name(const string name)
{
  return names[name];
}

void BaseClient::del_name(const ClientPtr client)
{
  names.erase(client->name);
}

bool BaseClient::is_client(const ClientPtr client)
{
  return typeid(*client) == typeid(Client);
}

bool BaseClient::is_server(const ClientPtr client)
{
  return typeid(*client) == typeid(Server);
}
<commit_msg>make the names list not case sensitive<commit_after>/*
  Copyright (c) 2012 Stuart Walsh

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

#include "stdinc.h"
#include <algorithm>
#include "baseclient.h"
#include "connection.h"
#include "server.h"
#include "system.h"

using std::transform;

unordered_map<string, ClientPtr> BaseClient::names;

BaseClient::BaseClient() : level(Unregistered)
{
  Logging::debug << "Created Client: " << this << Logging::endl;
}

BaseClient::~BaseClient()
{
  Logging::debug << "Destroyed Client: " << this << Logging::endl;
}

void BaseClient::send(string message)
{
  if (message.length() >= 510)
    message.resize(510);

  message.append("\r\n");

  connection->send(message);
}

string BaseClient::str() const
{
  if(name.empty())
    return "*";
  else
    return name;
}

bool BaseClient::is_registered() const
{
  return level >= Registered;
}

void BaseClient::clear_connection()
{
  connection.reset();
}

string BaseClient::get_name() const
{
  return name;
}

string BaseClient::get_host() const
{
  return host;
}

void BaseClient::set_name(const string _name)
{
  name = _name;
}

void BaseClient::set_registered()
{
  level = Registered;
}

void BaseClient::set_connection(const ConnectionPtr conn)
{
  connection = conn;
  host = connection->get_host();
}

//  Statics

void BaseClient::init()
{
  ClientPtr me = ClientPtr(new Server);
  shared_ptr<Server> me_ptr = dynamic_pointer_cast<Server>(me);

  me->set_name(System::get_server_name());
  me_ptr->set_info(System::get_server_info());

  Server::set_me(me);
}

void BaseClient::add_name(const ClientPtr client)
{
  string upper_name = client->name;

  transform(client->name.begin(), client->name.end(), upper_name.begin(), toupper);

  names[upper_name] = client;
}

ClientPtr BaseClient::find_by_name(const string name)
{
  string upper_name = name;

  transform(name.begin(), name.end(), upper_name.begin(), toupper);

  return names[upper_name];
}

void BaseClient::del_name(const ClientPtr client)
{
  string upper_name = client->name;

  transform(client->name.begin(), client->name.end(), upper_name.begin(), toupper);

  names.erase(upper_name);
}

bool BaseClient::is_client(const ClientPtr client)
{
  return typeid(*client) == typeid(Client);
}

bool BaseClient::is_server(const ClientPtr client)
{
  return typeid(*client) == typeid(Server);
}
<|endoftext|>