<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "io/FileReader.h"
#include "io/Buffer.h"          // for Buffer
#include "io/FileIOException.h" // for FileIOException
#include <cstdio>               // for fclose, fseek, fopen, fread, ftell
#include <fcntl.h>              // for SEEK_END, SEEK_SET

#if !defined(__unix__) && !defined(__APPLE__)
#include <io.h>
#include <tchar.h>
#include <windows.h>
#endif // !defined(__unix__) && !defined(__APPLE__)

namespace RawSpeed {

FileReader::FileReader(const char *_filename) : mFilename(_filename) {}

FileMap* FileReader::readFile() {
#if defined(__unix__) || defined(__APPLE__)
  int bytes_read = 0;
  FILE *file;
  char *dest;
  long size;

  file = fopen(mFilename, "rb");
  if (file == nullptr)
    ThrowFIE("Could not open file.");
  fseek(file, 0, SEEK_END);
  size = ftell(file);
  if (size <= 0) {
    fclose(file);
    ThrowFIE("File is 0 bytes.");
  }
  fseek(file, 0, SEEK_SET);

#if 0
  // Not used, as it is slower than sync read

  uchar8* pa = (uchar8*)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
  FileMap *fileData = new FileMap(pa, size);

#else
  auto *fileData = new FileMap(size);

  dest = (char *)fileData->getDataWrt(0, size);
  bytes_read = fread(dest, 1, size, file);
  fclose(file);
  if (size != bytes_read) {
    delete fileData;
    ThrowFIE("Could not read file.");
  }
#endif

#else // __unix__
  HANDLE file_h;  // File handle
  file_h = CreateFile(mFilename, GENERIC_READ, FILE_SHARE_READ, nullptr,
                      OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
  if (file_h == INVALID_HANDLE_VALUE) {
    ThrowFIE("Could not open file.");
  }

  LARGE_INTEGER f_size;
  GetFileSizeEx(file_h , &f_size);

  if (!f_size.LowPart)
    ThrowFIE("File is 0 bytes.");

  FileMap *fileData = new FileMap(f_size.LowPart);

  DWORD bytes_read;
  if (!ReadFile(file_h, fileData->getDataWrt(0, fileData->getSize()),
                fileData->getSize(), &bytes_read, nullptr)) {
    CloseHandle(file_h);
    delete fileData;
    ThrowFIE("Could not read file.");
  }
  CloseHandle(file_h);

#endif // __unix__
  return fileData;
}

} // namespace RawSpeed
<commit_msg>FileReader: convert to Buffer::Create()<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "io/FileReader.h"
#include "io/Buffer.h"          // for Buffer
#include "io/FileIOException.h" // for FileIOException
#include <algorithm>            // for move
#include <cstdio>               // for fclose, fseek, fopen, fread, ftell
#include <fcntl.h>              // for SEEK_END, SEEK_SET
#include <memory>               // for unique_ptr

#if !defined(__unix__) && !defined(__APPLE__)
#include <io.h>
#include <tchar.h>
#include <windows.h>
#endif // !defined(__unix__) && !defined(__APPLE__)

namespace RawSpeed {

FileReader::FileReader(const char *_filename) : mFilename(_filename) {}

FileMap* FileReader::readFile() {
#if defined(__unix__) || defined(__APPLE__)
  int bytes_read = 0;
  FILE *file;
  long size;

  file = fopen(mFilename, "rb");
  if (file == nullptr)
    ThrowFIE("Could not open file.");
  fseek(file, 0, SEEK_END);
  size = ftell(file);
  if (size <= 0) {
    fclose(file);
    ThrowFIE("File is 0 bytes.");
  }
  fseek(file, 0, SEEK_SET);

  auto dest = Buffer::Create(size);
  bytes_read = fread(dest.get(), 1, size, file);
  fclose(file);
  if (size != bytes_read)
    ThrowFIE("Could not read file.");

  auto* fileData = new Buffer(move(dest), size);

#else // __unix__

  HANDLE file_h;  // File handle
  file_h = CreateFile(mFilename, GENERIC_READ, FILE_SHARE_READ, nullptr,
                      OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
  if (file_h == INVALID_HANDLE_VALUE) {
    ThrowFIE("Could not open file.");
  }

  LARGE_INTEGER f_size;
  GetFileSizeEx(file_h , &f_size);

  if (!f_size.LowPart)
    ThrowFIE("File is 0 bytes.");

  auto dest = Buffer::Create(f_size.LowPart);

  DWORD bytes_read;
  if (!ReadFile(file_h, dest.get(), f_size.LowPart, &bytes_read, nullptr)) {
    CloseHandle(file_h);
    ThrowFIE("Could not read file.");
  }

  CloseHandle(file_h);

  auto* fileData = new Buffer(move(dest), f_size.LowPart);

#endif // __unix__

  return fileData;
}

} // namespace RawSpeed
<|endoftext|>


<commit_before>/*
 * encode_utils.cpp
 *
 * Author: Ming Tsang
 * Copyright (c) 2014 Ming Tsang
 * Refer to LICENSE for details
 */

#include <cstddef>
#include <iomanip>
#include <iterator>
#include <string>

#include "libutils/log.h"
#include "libutils/platform/endian_utils.h"
#include "libutils/str/encode_utils.h"
#include "libutils/str/str_utils.h"

using namespace std;

#define NS_TAG "libutils::str::"
#define TAG NS_TAG "EncodeUtils::"

namespace libutils
{
namespace str
{

size_t EncodeUtils::U16ToU8(const wchar_t u16, char *out_u8)
{
	if (u16 <= 0x007F)
	{
		// 0xxxxxxx to 0xxxxxxx
		out_u8[0] = u16;
		return 1;
	}
	else if (u16 <= 0x7FF)
	{
		// 00000yyy yyxxxxxx to 110yyyyy 10xxxxxx
		out_u8[0] = 0xC0 | ((u16 & 0x07C0) >> 6);
		out_u8[1] = 0x80 | (u16 & 0x003F);
		return 2;
	}
	else if (u16 <= 0xFFFF)
	{
		// zzzzyyyy yyxxxxxx to 1110zzzz 10yyyyyy 10xxxxxx
		out_u8[0] = 0xE0 | ((u16 & 0xF000) >> 12);
		out_u8[1] = 0x80 | ((u16 & 0x0FC0) >> 6);
		out_u8[2] = 0x80 | (u16 & 0x003F);
		return 3;
	}
	else if (u16 <= 0x10FFFF)
	{
		// 000aaazz zzzzyyyy yyxxxxxx to 11110aaa 10zzzzzz 10yyyyyy 10xxxxxx
		out_u8[0] = 0xF0 | ((u16 & 0x1C0000) >> 18);
		out_u8[1] = 0x80 | ((u16 & 0x03F000) >> 12);
		out_u8[2] = 0x80 | ((u16 & 0x000FC0) >> 6);
		out_u8[3] = 0x80 | (u16 & 0x003F);
		return 4;
	}
	else
	{
		// What...?
		LU_LOG_W(TAG "U16ToU8", "Invalid UTF-16 char (>0x10FFFF)");
		return 0;
	}
}

string EncodeUtils::U16ToU8(const wstring &u16_str, const bool is_shrink_str)
{
	string u8_str;
	u8_str.reserve(u16_str.size() * 3);

	for (wchar_t u16 : u16_str)
	{
		char u8[4];
		std::copy(u8, u8 + U16ToU8(u16, u8), back_insert_iterator<string>(u8_str));
	}

	if (is_shrink_str)
	{
		u8_str.shrink_to_fit();
	}
	return u8_str;
}

size_t EncodeUtils::U8ToU16(const char *u8, const size_t u8_size,
		wchar_t *out_u16)
{
	*out_u16 = 0;
	if (u8_size == 0)
	{
		LU_LOG_W(TAG "U8ToU16", "Empty data");
		return 0;
	}

	if ((u8[0] & 0xF8) == 0xF0)
	{
		// 11110xxx ...
		if (u8_size < 4)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x0E) << 18;
			*out_u16 |= (u8[1] & 0x3F) << 12;
			*out_u16 |= (u8[2] & 0x3F) << 6;
			*out_u16 |= (u8[3] & 0x3F);
		}
		return 4;
	}
	else if ((u8[0] & 0xF0) == 0xE0)
	{
		// 1110xxxx ...
		if (u8_size < 3)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x0F) << 12;
			*out_u16 |= (u8[1] & 0x3F) << 6;
			*out_u16 |= (u8[2] & 0x3F);
		}
		return 3;
	}
	else if ((u8[0] & 0xE0) == 0xC0)
	{
		// 110xxxxx ...
		if (u8_size < 2)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x1F) << 6;
			*out_u16 |= (u8[1] & 0x3F);
		}
		return 2;
	}
	else if (!(u8[0] & 0x80))
	{
		// 0xxxxxxx
		*out_u16 = u8[0];
		return 1;
	}
	else
	{
		// What...?
		LU_LOG_W(TAG "U8ToU16", StrUtils::Concat("Invalid UTF-8 char (0x",
				std::hex, setw(8), setfill('0'), u8[0], ')'));
		return 0;
	}
}

wstring EncodeUtils::U8ToU16(const string &u8_str, const bool is_shrink_str)
{
	wstring u16_str;
	u16_str.reserve(u8_str.size());

	size_t i = 0;
	while (i < u8_str.size())
	{
		wchar_t u16;
		const size_t u8_size = U8ToU16(u8_str.data() + i, u8_str.size() - i,
				&u16);
		if (u8_size == 0)
		{
			++i;
		}
		else
		{
			if (i + u8_size <= u8_str.size())
			{
				u16_str.push_back(u16);
			}
			i += u8_size;
		}
	}

	if (is_shrink_str)
	{
		u16_str.shrink_to_fit();
	}
	return u16_str;
}

}
}
<commit_msg>Remove redundant include<commit_after>/*
 * encode_utils.cpp
 *
 * Author: Ming Tsang
 * Copyright (c) 2014 Ming Tsang
 * Refer to LICENSE for details
 */

#include <cstddef>
#include <iomanip>
#include <iterator>
#include <string>

#include "libutils/log.h"
#include "libutils/str/encode_utils.h"
#include "libutils/str/str_utils.h"

using namespace std;

#define NS_TAG "libutils::str::"
#define TAG NS_TAG "EncodeUtils::"

namespace libutils
{
namespace str
{

size_t EncodeUtils::U16ToU8(const wchar_t u16, char *out_u8)
{
	if (u16 <= 0x007F)
	{
		// 0xxxxxxx to 0xxxxxxx
		out_u8[0] = u16;
		return 1;
	}
	else if (u16 <= 0x7FF)
	{
		// 00000yyy yyxxxxxx to 110yyyyy 10xxxxxx
		out_u8[0] = 0xC0 | ((u16 & 0x07C0) >> 6);
		out_u8[1] = 0x80 | (u16 & 0x003F);
		return 2;
	}
	else if (u16 <= 0xFFFF)
	{
		// zzzzyyyy yyxxxxxx to 1110zzzz 10yyyyyy 10xxxxxx
		out_u8[0] = 0xE0 | ((u16 & 0xF000) >> 12);
		out_u8[1] = 0x80 | ((u16 & 0x0FC0) >> 6);
		out_u8[2] = 0x80 | (u16 & 0x003F);
		return 3;
	}
	else if (u16 <= 0x10FFFF)
	{
		// 000aaazz zzzzyyyy yyxxxxxx to 11110aaa 10zzzzzz 10yyyyyy 10xxxxxx
		out_u8[0] = 0xF0 | ((u16 & 0x1C0000) >> 18);
		out_u8[1] = 0x80 | ((u16 & 0x03F000) >> 12);
		out_u8[2] = 0x80 | ((u16 & 0x000FC0) >> 6);
		out_u8[3] = 0x80 | (u16 & 0x003F);
		return 4;
	}
	else
	{
		// What...?
		LU_LOG_W(TAG "U16ToU8", "Invalid UTF-16 char (>0x10FFFF)");
		return 0;
	}
}

string EncodeUtils::U16ToU8(const wstring &u16_str, const bool is_shrink_str)
{
	string u8_str;
	u8_str.reserve(u16_str.size() * 3);

	for (wchar_t u16 : u16_str)
	{
		char u8[4];
		std::copy(u8, u8 + U16ToU8(u16, u8), back_insert_iterator<string>(u8_str));
	}

	if (is_shrink_str)
	{
		u8_str.shrink_to_fit();
	}
	return u8_str;
}

size_t EncodeUtils::U8ToU16(const char *u8, const size_t u8_size,
		wchar_t *out_u16)
{
	*out_u16 = 0;
	if (u8_size == 0)
	{
		LU_LOG_W(TAG "U8ToU16", "Empty data");
		return 0;
	}

	if ((u8[0] & 0xF8) == 0xF0)
	{
		// 11110xxx ...
		if (u8_size < 4)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x0E) << 18;
			*out_u16 |= (u8[1] & 0x3F) << 12;
			*out_u16 |= (u8[2] & 0x3F) << 6;
			*out_u16 |= (u8[3] & 0x3F);
		}
		return 4;
	}
	else if ((u8[0] & 0xF0) == 0xE0)
	{
		// 1110xxxx ...
		if (u8_size < 3)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x0F) << 12;
			*out_u16 |= (u8[1] & 0x3F) << 6;
			*out_u16 |= (u8[2] & 0x3F);
		}
		return 3;
	}
	else if ((u8[0] & 0xE0) == 0xC0)
	{
		// 110xxxxx ...
		if (u8_size < 2)
		{
			LU_LOG_W(TAG "U8ToU16", "Insufficient data");
		}
		else
		{
			*out_u16 |= (u8[0] & 0x1F) << 6;
			*out_u16 |= (u8[1] & 0x3F);
		}
		return 2;
	}
	else if (!(u8[0] & 0x80))
	{
		// 0xxxxxxx
		*out_u16 = u8[0];
		return 1;
	}
	else
	{
		// What...?
		LU_LOG_W(TAG "U8ToU16", StrUtils::Concat("Invalid UTF-8 char (0x",
				std::hex, setw(8), setfill('0'), u8[0], ')'));
		return 0;
	}
}

wstring EncodeUtils::U8ToU16(const string &u8_str, const bool is_shrink_str)
{
	wstring u16_str;
	u16_str.reserve(u8_str.size());

	size_t i = 0;
	while (i < u8_str.size())
	{
		wchar_t u16;
		const size_t u8_size = U8ToU16(u8_str.data() + i, u8_str.size() - i,
				&u16);
		if (u8_size == 0)
		{
			++i;
		}
		else
		{
			if (i + u8_size <= u8_str.size())
			{
				u16_str.push_back(u16);
			}
			i += u8_size;
		}
	}

	if (is_shrink_str)
	{
		u16_str.shrink_to_fit();
	}
	return u16_str;
}

}
}
<|endoftext|>


<commit_before>/*
 * cl_denoise_handler.cpp - CL denoise handler
 *
 *  Copyright (c) 2015 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.
 *
 * Author: Juan Zhao <juan.j.zhao@intel.com>
 */

#include "xcam_utils.h"
#include "cl_denoise_handler.h"

namespace XCam {

CLDenoiseImageKernel::CLDenoiseImageKernel (SmartPtr<CLContext> &context,
        const char *name)
    : CLImageKernel (context, name, false)
    , _sigma_r (10.0)
    , _imw (1920)
    , _imh (1080)
{
}

XCamReturn
CLDenoiseImageKernel::prepare_arguments (
    SmartPtr<DrmBoBuffer> &input, SmartPtr<DrmBoBuffer> &output,
    CLArgument args[], uint32_t &arg_count,
    CLWorkSize &work_size)
{
    SmartPtr<CLContext> context = get_context ();
    const VideoBufferInfo & video_info = input->get_video_info ();

    _imw = video_info.width;
    _imh = (video_info.size / video_info.strides[0]) / 4 * 4;
    //sigma_r = 0.1*100
    _sigma_r = 10.0;

    _image_in = new CLVaImage (context, input);
    _image_out = new CLVaImage (context, output);

    XCAM_ASSERT (_image_in->is_valid () && _image_out->is_valid ());
    XCAM_FAIL_RETURN (
        WARNING,
        _image_in->is_valid () && _image_out->is_valid (),
        XCAM_RETURN_ERROR_MEM,
        "cl image kernel(%s) in/out memory not available", get_kernel_name ());

    //set args;
    args[0].arg_adress = &_image_in->get_mem_id ();
    args[0].arg_size = sizeof (cl_mem);
    args[1].arg_adress = &_image_out->get_mem_id ();
    args[1].arg_size = sizeof (cl_mem);
    args[2].arg_adress = &_sigma_r;
    args[2].arg_size = sizeof (_sigma_r);
    args[3].arg_adress = &_imw;
    args[3].arg_size = sizeof (_imw);
    args[4].arg_adress = &_imh;
    args[4].arg_size = sizeof (_imh);
    arg_count = 5;

    work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    work_size.global[0] = _imh;
    work_size.global[1] = _imw;

    return XCAM_RETURN_NO_ERROR;
}

CLDenoiseImageHandler::CLDenoiseImageHandler (const char *name)
    : CLImageHandler (name)
{
}

bool
CLDenoiseImageHandler::set_mode (uint32_t mode)
{
    if (mode == CL_DENOISE_TYPE_BILATERIAL)
        _bilateral_kernel->set_enable (true);

    return true;
}

bool
CLDenoiseImageHandler::set_bi_kernel (SmartPtr<CLDenoiseImageKernel> &kernel)
{
    SmartPtr<CLImageKernel> image_kernel = kernel;
    add_kernel (image_kernel);
    _bilateral_kernel = kernel;
    return true;
}

SmartPtr<CLImageHandler>
create_cl_denoise_image_handler (SmartPtr<CLContext> &context)
{
    SmartPtr<CLDenoiseImageHandler> denoise_handler;
    SmartPtr<CLDenoiseImageKernel> denoise_kernel;
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    denoise_kernel = new CLDenoiseImageKernel (context, "kernel_denoise");
    {
        XCAM_CL_KERNEL_FUNC_SOURCE_BEGIN(kernel_denoise)
#include "kernel_denoise.cl"
        XCAM_CL_KERNEL_FUNC_END;
        ret = denoise_kernel->load_from_source (kernel_denoise_body, strlen (kernel_denoise_body));
        XCAM_FAIL_RETURN (
            WARNING,
            ret == XCAM_RETURN_NO_ERROR,
            NULL,
            "CL image handler(%s) load source failed", denoise_kernel->get_kernel_name());
    }
    XCAM_ASSERT (denoise_kernel->is_valid ());
    denoise_handler = new CLDenoiseImageHandler ("cl_handler_denoise");
    denoise_handler->set_bi_kernel (denoise_kernel);

    return denoise_handler;
}

};
<commit_msg>cl denoise: enable/disable according to mode setting<commit_after>/*
 * cl_denoise_handler.cpp - CL denoise handler
 *
 *  Copyright (c) 2015 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.
 *
 * Author: Juan Zhao <juan.j.zhao@intel.com>
 */

#include "xcam_utils.h"
#include "cl_denoise_handler.h"

namespace XCam {

CLDenoiseImageKernel::CLDenoiseImageKernel (SmartPtr<CLContext> &context,
        const char *name)
    : CLImageKernel (context, name, false)
    , _sigma_r (10.0)
    , _imw (1920)
    , _imh (1080)
{
}

XCamReturn
CLDenoiseImageKernel::prepare_arguments (
    SmartPtr<DrmBoBuffer> &input, SmartPtr<DrmBoBuffer> &output,
    CLArgument args[], uint32_t &arg_count,
    CLWorkSize &work_size)
{
    SmartPtr<CLContext> context = get_context ();
    const VideoBufferInfo & video_info = input->get_video_info ();

    _imw = video_info.width;
    _imh = (video_info.size / video_info.strides[0]) / 4 * 4;
    //sigma_r = 0.1*100
    _sigma_r = 10.0;

    _image_in = new CLVaImage (context, input);
    _image_out = new CLVaImage (context, output);

    XCAM_ASSERT (_image_in->is_valid () && _image_out->is_valid ());
    XCAM_FAIL_RETURN (
        WARNING,
        _image_in->is_valid () && _image_out->is_valid (),
        XCAM_RETURN_ERROR_MEM,
        "cl image kernel(%s) in/out memory not available", get_kernel_name ());

    //set args;
    args[0].arg_adress = &_image_in->get_mem_id ();
    args[0].arg_size = sizeof (cl_mem);
    args[1].arg_adress = &_image_out->get_mem_id ();
    args[1].arg_size = sizeof (cl_mem);
    args[2].arg_adress = &_sigma_r;
    args[2].arg_size = sizeof (_sigma_r);
    args[3].arg_adress = &_imw;
    args[3].arg_size = sizeof (_imw);
    args[4].arg_adress = &_imh;
    args[4].arg_size = sizeof (_imh);
    arg_count = 5;

    work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    work_size.global[0] = _imh;
    work_size.global[1] = _imw;

    return XCAM_RETURN_NO_ERROR;
}

CLDenoiseImageHandler::CLDenoiseImageHandler (const char *name)
    : CLImageHandler (name)
{
}

bool
CLDenoiseImageHandler::set_mode (uint32_t mode)
{
    _bilateral_kernel->set_enable (mode == CL_DENOISE_TYPE_BILATERIAL);

    return true;
}

bool
CLDenoiseImageHandler::set_bi_kernel (SmartPtr<CLDenoiseImageKernel> &kernel)
{
    SmartPtr<CLImageKernel> image_kernel = kernel;
    add_kernel (image_kernel);
    _bilateral_kernel = kernel;
    return true;
}

SmartPtr<CLImageHandler>
create_cl_denoise_image_handler (SmartPtr<CLContext> &context)
{
    SmartPtr<CLDenoiseImageHandler> denoise_handler;
    SmartPtr<CLDenoiseImageKernel> denoise_kernel;
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    denoise_kernel = new CLDenoiseImageKernel (context, "kernel_denoise");
    {
        XCAM_CL_KERNEL_FUNC_SOURCE_BEGIN(kernel_denoise)
#include "kernel_denoise.cl"
        XCAM_CL_KERNEL_FUNC_END;
        ret = denoise_kernel->load_from_source (kernel_denoise_body, strlen (kernel_denoise_body));
        XCAM_FAIL_RETURN (
            WARNING,
            ret == XCAM_RETURN_NO_ERROR,
            NULL,
            "CL image handler(%s) load source failed", denoise_kernel->get_kernel_name());
    }
    XCAM_ASSERT (denoise_kernel->is_valid ());
    denoise_handler = new CLDenoiseImageHandler ("cl_handler_denoise");
    denoise_handler->set_bi_kernel (denoise_kernel);

    return denoise_handler;
}

};
<|endoftext|>


<commit_before>#include "statisticspage.h"
#include "ui_statisticspage.h"
#include "main.h"
#include "wallet.h"
#include "init.h"
#include "base58.h"
#include "clientmodel.h"
#include "bitcoinrpc.h"
#include <sstream>
#include <string>

using namespace json_spirit;

StatisticsPage::StatisticsPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::StatisticsPage)
{
    ui->setupUi(this);

    setFixedSize(400, 420);

    connect(ui->startButton, SIGNAL(pressed()), this, SLOT(updateStatistics()));
}

int heightPrevious = -1;
int connectionPrevious = -1;
int volumePrevious = -1;
double rewardPrevious = -1;
double netPawratePrevious = -1;
double pawratePrevious = -1;
double hardnessPrevious = -1;
double hardnessPrevious2 = -1;
int stakeminPrevious = -1;
int stakemaxPrevious = -1;
QString stakecPrevious = "";

void StatisticsPage::updateStatistics()
{
    double pHardness = GetDifficulty();
    double pHardness2 = GetDifficulty(GetLastBlockIndex(pindexBest, true));
    int pPawrate = GetPoWMHashPS();
    double pPawrate2 = 0.000;
    int nHeight = pindexBest->nHeight;
    uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0;
    pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight);
    uint64_t nNetworkWeight = GetPoSKernelPS();
    int64_t volume = ((pindexBest->nMoneySupply)/100000000);
    int peers = this->model->getNumConnections();
    pPawrate2 = (double)pPawrate;
    QString height = QString::number(nHeight);
    QString stakemin = QString::number(nMinWeight);
    QString stakemax = QString::number(nNetworkWeight);
    QString phase = "";
    if (pindexBest->nHeight < 1)
    {
        phase = "ICO";
    }
    else if(pindexBest->nHeight > 1)
	{
		phase = "PoS Phase";
	}

	QString subsidy = "";
	if(pindexBest->nHeight < 1)
    {
        subsidy = "ICO";
    }
    else if(pindexBest->nHeight > 1)
    {
        subsidy = "PoS Phase";
    }

	QString hardness = QString::number(pHardness, 'f', 6);
    QString hardness2 = QString::number(pHardness2, 'f', 6);
    QString pawrate = QString::number(pPawrate2, 'f', 3);
    QString Qlpawrate = model->getLastBlockDate().toString();

    QString QPeers = QString::number(peers);
    QString qVolume = QLocale(QLocale::English).toString(volume);

    if(nHeight > heightPrevious)
    {
        ui->heightBox->setText("" + height + "");
    } else {
    ui->heightBox->setText(height);
    }

    if(0 > stakeminPrevious)
    {
        ui->minBox->setText("" + stakemin + "");
    } else {
    ui->minBox->setText(stakemin);
    }
    if(0 > stakemaxPrevious)
    {
        ui->maxBox->setText("" + stakemax + "");
    } else {
    ui->maxBox->setText(stakemax);
    }

    if(phase != stakecPrevious)
    {
        ui->cBox->setText("" + phase + "");
    } else {
    ui->cBox->setText(phase);
    }

    if(subsidy != rewardPrevious)
    {
        ui->rewardBox->setText("" + subsidy + "");
    } else {
    ui->rewardBox->setText(subsidy);
    }

    if(pHardness > hardnessPrevious)
    {
        ui->diffBox->setText("" + hardness + "");
    } else if(pHardness < hardnessPrevious) {
        ui->diffBox->setText("" + hardness + "");
    } else {
        ui->diffBox->setText(hardness);
    }

    if(pHardness2 > hardnessPrevious2)
    {
        ui->diffBox2->setText("" + hardness2 + "");
    } else if(pHardness2 < hardnessPrevious2) {
        ui->diffBox2->setText("" + hardness2 + "");
    } else {
        ui->diffBox2->setText(hardness2);
    }

    if(pPawrate2 > netPawratePrevious)
    {
        ui->pawrateBox->setText("" + pawrate + " MH/s");
    } else if(pPawrate2 < netPawratePrevious) {
        ui->pawrateBox->setText("" + pawrate + " MH/s");
    } else {
        ui->pawrateBox->setText(pawrate + " MH/s");
    }

    if(Qlpawrate != pawratePrevious)
    {
        ui->localBox->setText("" + Qlpawrate + "");
    } else {
    ui->localBox->setText(Qlpawrate);
    }

    if(peers > connectionPrevious)
    {
        ui->connectionBox->setText("" + QPeers + "");
    } else if(peers < connectionPrevious) {
        ui->connectionBox->setText("" + QPeers + "");
    } else {
        ui->connectionBox->setText(QPeers);
    }

    if(volume > volumePrevious)
    {
        ui->volumeBox->setText("" + qVolume + " BLOCKS" + "");
    } else if(volume < volumePrevious) {
        ui->volumeBox->setText("" + qVolume + " BLOCKS" + "");
    } else {
        ui->volumeBox->setText(qVolume + " BLOCKS");
    }
    updatePrevious(nHeight, nMinWeight, nNetworkWeight, phase, subsidy, pHardness, pHardness2, pPawrate2, Qlpawrate, peers, volume);
}

void StatisticsPage::updatePrevious(int nHeight, int nMinWeight, int nNetworkWeight, QString phase, QString subsidy, double pHardness, double pHardness2, double pPawrate2, QString Qlpawrate, int peers, int volume)
{
    heightPrevious = nHeight;
    stakeminPrevious = nMinWeight;
    stakemaxPrevious = nNetworkWeight;
    stakecPrevious = phase;
    rewardPrevious = subsidy;
    hardnessPrevious = pHardness;
    hardnessPrevious2 = pHardness2;
    netPawratePrevious = pPawrate2;
    pawratePrevious = Qlpawrate;
    connectionPrevious = peers;
    volumePrevious = volume;
}

void StatisticsPage::setModel(ClientModel *model)
{
    updateStatistics();
    this->model = model;
}

StatisticsPage::~StatisticsPage()
{
    delete ui;
}
<commit_msg>fix build<commit_after>#include "statisticspage.h"
#include "ui_statisticspage.h"
#include "main.h"
#include "wallet.h"
#include "init.h"
#include "base58.h"
#include "clientmodel.h"
#include "bitcoinrpc.h"
#include <sstream>
#include <string>

using namespace json_spirit;

StatisticsPage::StatisticsPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::StatisticsPage)
{
    ui->setupUi(this);

    setFixedSize(400, 420);

    connect(ui->startButton, SIGNAL(pressed()), this, SLOT(updateStatistics()));
}

int heightPrevious = -1;
int connectionPrevious = -1;
int volumePrevious = -1;
double rewardPrevious = -1;
double netPawratePrevious = -1;
double pawratePrevious = -1;
double hardnessPrevious = -1;
double hardnessPrevious2 = -1;
int stakeminPrevious = -1;
int stakemaxPrevious = -1;
QString stakecPrevious = "";

void StatisticsPage::updateStatistics()
{
    double pHardness = GetDifficulty();
    double pHardness2 = GetDifficulty(GetLastBlockIndex(pindexBest, true));
    int pPawrate = GetPoWMHashPS();
    double pPawrate2 = 0.000;
    int nHeight = pindexBest->nHeight;
    uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0;
    pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight);
    uint64_t nNetworkWeight = GetPoSKernelPS();
    int64_t volume = ((pindexBest->nMoneySupply)/100000000);
    int peers = this->model->getNumConnections();
    pPawrate2 = (double)pPawrate;
    QString height = QString::number(nHeight);
    QString stakemin = QString::number(nMinWeight);
    QString stakemax = QString::number(nNetworkWeight);
    QString phase = "";
    if (pindexBest->nHeight < 1)
    {
        phase = "ICO";
    }
    else if(pindexBest->nHeight > 1)
	{
		phase = "PoS Phase";
	}

	QString subsidy = "";
	if(pindexBest->nHeight < 1)
    {
        subsidy = "ICO";
    }
    else if(pindexBest->nHeight > 1)
    {
        subsidy = "PoS Phase";
    }

	QString hardness = QString::number(pHardness, 'f', 6);
    QString hardness2 = QString::number(pHardness2, 'f', 6);
    QString pawrate = QString::number(pPawrate2, 'f', 3);
    QString Qlpawrate = model->getLastBlockDate().toString();

    QString QPeers = QString::number(peers);
    QString qVolume = QString::number(volume);

    if(nHeight > heightPrevious)
    {
        ui->heightBox->setText("" + height + "");
    } else {
    ui->heightBox->setText(height);
    }

    if(0 > stakeminPrevious)
    {
        ui->minBox->setText("" + stakemin + "");
    } else {
    ui->minBox->setText(stakemin);
    }
    if(0 > stakemaxPrevious)
    {
        ui->maxBox->setText("" + stakemax + "");
    } else {
    ui->maxBox->setText(stakemax);
    }

    if(phase != stakecPrevious)
    {
        ui->cBox->setText("" + phase + "");
    } else {
    ui->cBox->setText(phase);
    }

    if(subsidy != rewardPrevious)
    {
        ui->rewardBox->setText("" + subsidy + "");
    } else {
    ui->rewardBox->setText(subsidy);
    }

    if(pHardness > hardnessPrevious)
    {
        ui->diffBox->setText("" + hardness + "");
    } else if(pHardness < hardnessPrevious) {
        ui->diffBox->setText("" + hardness + "");
    } else {
        ui->diffBox->setText(hardness);
    }

    if(pHardness2 > hardnessPrevious2)
    {
        ui->diffBox2->setText("" + hardness2 + "");
    } else if(pHardness2 < hardnessPrevious2) {
        ui->diffBox2->setText("" + hardness2 + "");
    } else {
        ui->diffBox2->setText(hardness2);
    }

    if(pPawrate2 > netPawratePrevious)
    {
        ui->pawrateBox->setText("" + pawrate + " MH/s");
    } else if(pPawrate2 < netPawratePrevious) {
        ui->pawrateBox->setText("" + pawrate + " MH/s");
    } else {
        ui->pawrateBox->setText(pawrate + " MH/s");
    }

    if(Qlpawrate != pawratePrevious)
    {
        ui->localBox->setText("" + Qlpawrate + "");
    } else {
    ui->localBox->setText(Qlpawrate);
    }

    if(peers > connectionPrevious)
    {
        ui->connectionBox->setText("" + QPeers + "");
    } else if(peers < connectionPrevious) {
        ui->connectionBox->setText("" + QPeers + "");
    } else {
        ui->connectionBox->setText(QPeers);
    }

    if(volume > volumePrevious)
    {
        ui->volumeBox->setText("" + qVolume + " BLOCKS" + "");
    } else if(volume < volumePrevious) {
        ui->volumeBox->setText("" + qVolume + " BLOCKS" + "");
    } else {
        ui->volumeBox->setText(qVolume + " BLOCKS");
    }
    updatePrevious(nHeight, nMinWeight, nNetworkWeight, phase, subsidy, pHardness, pHardness2, pPawrate2, Qlpawrate, peers, volume);
}

void StatisticsPage::updatePrevious(int nHeight, int nMinWeight, int nNetworkWeight, QString phase, QString subsidy, double pHardness, double pHardness2, double pPawrate2, QString Qlpawrate, int peers, int volume)
{
    heightPrevious = nHeight;
    stakeminPrevious = nMinWeight;
    stakemaxPrevious = nNetworkWeight;
    stakecPrevious = phase;
    rewardPrevious = subsidy;
    hardnessPrevious = pHardness;
    hardnessPrevious2 = pHardness2;
    netPawratePrevious = pPawrate2;
    pawratePrevious = Qlpawrate;
    connectionPrevious = peers;
    volumePrevious = volume;
}

void StatisticsPage::setModel(ClientModel *model)
{
    updateStatistics();
    this->model = model;
}

StatisticsPage::~StatisticsPage()
{
    delete ui;
}
<|endoftext|>


<commit_before>#ifdef _WIN32
#include <windows.h>
#endif
#ifdef unix
#include <iostream>
#endif
#include <RefeusProcess.h>

#ifdef _WIN32
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {

  RefeusProcess r;
  char *command_line_cstr = GetCommandLine();
  std::string command_line = command_line_cstr;
  r.configureLanguageFromAPICode(GetUserDefaultLCID());
  if (r.argParser(command_line) ) {
    r.start();
  }
}
#endif

#ifdef unix
int main(int argc, char** argv) {
  RefeusProcess r;
  std::string command_line= "";
  for ( int i = 1
      ; i < argc
      ; i++
      ) {
    std::string argv_item = std::string(argv[i]);
    if ( argv_item.find(" ") != std::string::npos ){
      argv_item = "\"" + argv_item + "\"";
    }
    command_line.append(argv_item.append(" "));
  }
  r.configureLanguageFromAPICode(1031);
  if (r.argParser(command_line)) {
    //rp.setEnvironment("window_size", "400x800");
    //rip.setExecutable("node.exe");
    //rip.setExecutableParameter("app.js");
    r.start();
  }
  //return r.start();
  //rip.start();
  //system("pause");
}
#endif
<commit_msg>updated function names<commit_after>#ifdef _WIN32
#include <windows.h>
#endif
#ifdef unix
#include <iostream>
#endif
#include <RefeusProcess.h>

#ifdef _WIN32
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {

  RefeusProcess r;

  char *command_line_cstr = GetCommandLine();
  std::string command_line = command_line_cstr;

  if (r.argParser(command_line) ) {
   r.configureDriveType();
   r.configureLanguage();
   r.start();
  }
}
#endif

#ifdef unix
int main(int argc, char** argv) {
  RefeusProcess r;
  std::string command_line= "";
  for ( int i = 1
      ; i < argc
      ; i++
      ) {
    std::string argv_item = std::string(argv[i]);
    if ( argv_item.find(" ") != std::string::npos ){
      argv_item = "\"" + argv_item + "\"";
    }
    command_line.append(argv_item.append(" "));
  }
  r.configureLanguageFromAPICode(1031);
  if (r.argParser(command_line)) {
    //rp.setEnvironment("window_size", "400x800");
    //rip.setExecutable("node.exe");
    //rip.setExecutableParameter("app.js");
    r.start();
  }
  //return r.start();
  //rip.start();
  //system("pause");
}
#endif
<|endoftext|>


<commit_before>/*
 * MarketControl.cpp
 *
 *  Created on: Jun 11, 2017
 *      Author: ondra
 */

#include "marketControl.h"

#include <couchit/couchDB.h>
#include <couchit/exception.h>
#include <couchit/query.h>
#include <imtjson/rpc.h>
#include "../common/config.h"

namespace quark {

MarketControl::MarketControl(Value cfg, StrViewA dbname)
	:ordersDb(initCouchDBConfig(cfg,dbname,"-orders"))
	,tradesDb(initCouchDBConfig(cfg,dbname,"-trades"))
	,posDb(initCouchDBConfig(cfg,dbname,"-positions"))
	,orderControl(ordersDb)
{

}

static void notImpl(RpcRequest req) {
	req.setError(501,"Not implemented yet!");
}

bool MarketControl::testDatabase() {
	CouchDB::PConnection conn = ordersDb.getConnection("");
	try {
		ordersDb.requestGET(conn,nullptr,0);
		return true;
	} catch (const couchit::RequestError &e) {
		if (e.getCode() == 404) return false;
		throw;
	}
}

Value MarketControl::getMarketStatus()  {

	Value err = ordersDb.get("error",CouchDB::flgNullIfMissing);
	if (err == nullptr) {
		return Object("marketStatus","ok");
	} else {
		return Object("marketStatus","stopped")
				("reason",err);
	}

}

Value MarketControl::initRpc(RpcServer& rpcServer) {

	PMarketControl me = this;
	rpcServer.add("Order.create", me, &MarketControl::rpcOrderCreate);
	rpcServer.add("Order.modify", me, &MarketControl::rpcOrderUpdate);
	rpcServer.add("Order.cancel", me, &MarketControl::rpcOrderCancel);
	rpcServer.add("Order.get", me, &MarketControl::rpcOrderGet);
	rpcServer.add("Stream.orders",  me, &MarketControl::rpcStreamOrders);
	rpcServer.add("Stream.trades", me, &MarketControl::rpcStreamTrades);
	rpcServer.add("Stream.orderbook", me, &MarketControl::rpcStreamOrderbook);
	rpcServer.add("Stream.positions", me, &MarketControl::rpcStreamPositions);
	rpcServer.add("Stream.lastId", me, &MarketControl::rpcStreamLastId);
	rpcServer.add("Status.get", me, &MarketControl::rpcStatusGet);
	rpcServer.add("Status.clear", me, &MarketControl::rpcStatusClear);
	rpcServer.add("Orderbook.get",me, &MarketControl::rpcOrderbookGet);

	return getMarketStatus();

}

void MarketControl::rpcOrderCreate(RpcRequest rq) {
	static Value chkargs (json::array,{Object("%","any")});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.create(args[0]));
	} catch (ValidatonError &e) {
		rq.setError(400,"Validation failed", e.getError());
	}
}

void MarketControl::rpcOrderUpdate(RpcRequest rq) {
	static Value chkargs1 = {"string",Object("%","any")};
	static Value chkargs2 = {"string",Object("%","any"), "string"};
	Value args = rq.getArgs();
	try {
		if (rq.checkArgs(chkargs1)) {
			rq.setResult(orderControl.modify(args[0],args[1],json::undefined));
		} else if (rq.checkArgs(chkargs2)) {
			rq.setResult(orderControl.modify(args[0],args[1],args[2]));
		} else {
			rq.setArgError();
		}
	} catch (ValidatonError &e) {
		rq.setError(400,"Validation failed", e.getError());
	} catch (OrderNotFoundError &e) {
		rq.setError(404,"Order not found");
	} catch (ConflictError &e) {
		rq.setError(409,"Conflict",e.getActualDoc());
	}
}

void MarketControl::rpcOrderCancel(RpcRequest rq) {
	static Value chkargs (json::array,{"string"});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.cancel(args[0]));
	} catch (OrderNotFoundError &e) {
		rq.setError(404,"Order not found");
	}
}

void MarketControl::rpcOrderGet(RpcRequest rq) {
	static Value chkargs (json::array,{"string"});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.getOrder(args[0]));
	} catch (const couchit::RequestError &e) {
		rq.setError(404,"Order not found");
	}
}

class MarketControl::BasicFeed: public FeedControl {
public:
	BasicFeed(couchit::CouchDB &db,
			  Value since,
			  RpcRequest rq,
			  String streamName)
				:FeedControl(db,since),rq(rq),streamName(streamName) {

	}
	virtual void init() override {
	}
	~BasicFeed() {
		stop();
	}

protected:
	RpcRequest rq;
	String streamName;
};

class MarketControl::OrderFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		static couchit::View initView("_design/index/_view/queue",couchit::View::includeDocs|couchit::View::update);
		initialView = &initView;
		feed.setFilter(couchit::Filter("index/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("id",doc["_id"])
				("_id",undefined)});
	}

};

class MarketControl::TradesFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		feed.setFilter(couchit::Filter("trades/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("id",doc["_id"])
				("_id",undefined)
				("_rev",undefined)
		});
	}

};

class MarketControl::PosFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		feed.setFilter(couchit::Filter("positions/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("user",doc["_id"].getString().substr(2))
				("_id",undefined)
				("_rev",undefined)
		});
	}
};

class MarketControl::OrderbookFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		static couchit::View initView("_design/index/_view/orderbook",couchit::View::includeDocs|couchit::View::update);
		this->initialView = &initView;
		feed.setFilter(couchit::Filter("orderbook/orders",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		sendNotify(rq, streamName, doc, seqNum.toString());
	}
	static void sendNotify(RpcRequest &rq, StrViewA streamName, Value doc, Value seq) {
		Object ntf;
		bool finished = doc["finished"].getBool();
		rq.sendNotify(streamName,{seq,{doc["_id"],doc["dir"],doc["limitPrice"],finished?Value(0):doc["size"]}});
	}

};

void MarketControl::rpcStreamOrders(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		ordersFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		ordersFeed = new OrderFeed(ordersDb, since, rq, "order");
		ordersFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamTrades(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		tradesFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		tradesFeed = new TradesFeed(tradesDb, since, rq, "trade");
		tradesFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamPositions(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		posFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		posFeed = new PosFeed(posDb, since, rq, "position");
		posFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamOrderbook(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		orderbookFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		orderbookFeed = new OrderbookFeed(ordersDb, since, rq, "orderbook");
		orderbookFeed->start();
		rq.setResult(true);
	} else {
		rq.setArgError();
	}
}

void MarketControl::FeedControl::stop() {

	if (!stopped) {
		feed.cancelWait();
		thr.join();
		stopped = true;
	}
}

void MarketControl::FeedControl::start() {
	bool initWait = false;
	using namespace couchit;
	std::condition_variable initWaitCond;
	std::mutex lock;

	thr = std::thread([&]{

		init();

		{
		std::unique_lock<std::mutex> _(lock);
		initWait = true;
		initWaitCond.notify_all();
		}

		Value lastDoc;
		if (!since.defined() && initialView != nullptr)
		{
			Query q = db.createQuery(*initialView);
			Result r = q.exec();
			for (Row rw : r) {
				onEvent(r.getUpdateSeq(),rw.doc);
				lastDoc = rw.doc;
			}
			since = r.getUpdateSeq();
		}

		if (since.defined())
			feed.since(since);
		try {
			feed >> [&](ChangedDoc x) {
				if (x.doc == lastDoc) return true;
				lastDoc = json::undefined;
				onEvent(x.seqId, x.doc);
				return true;
			};
		} catch (couchit::CanceledException &) {

		}
	});

	std::unique_lock<std::mutex> _(lock);
	initWaitCond.wait(_,[&]{return initWait;});
	stopped = false;
}

MarketControl::FeedControl::FeedControl(CouchDB& db, Value since)
	:feed(db.createChangesFeed()),  since(since), db(db), stopped(true)
{
	feed.setTimeout(-1);
	feed.includeDocs(true);
}

void MarketControl::rpcStreamLastId(RpcRequest rq) {
	if (!rq.checkArgs(json::array)) return rq.setArgError();

	rq.setResult(Object("orders",ordersDb.getLastSeqNumber())
					   ("trades",tradesDb.getLastSeqNumber())
					   ("positions",posDb.getLastSeqNumber())
			);

}

void quark::MarketControl::rpcStatusGet(RpcRequest rq) {
	rq.setResult(getMarketStatus());
}

void quark::MarketControl::rpcStatusClear(RpcRequest rq) {
	couchit::Document doc = ordersDb.get("error");
	doc.setDeleted();
	ordersDb.put(doc);
	rq.setResult(getMarketStatus());
}

void quark::MarketControl::rpcOrderbookGet(RpcRequest rq) {
	couchit::View orderbookView("_design/index/_view/orderbook",couchit::View::update);
	couchit::Result res = ordersDb.createQuery(orderbookView).exec();
	Array out;
	for (couchit::Row rw : res) {
		out.push_back({rw["id"],rw.key[0], rw.key[1], rw.value});
	}
	rq.setResult(out);
}

}

/* namespace quark */

<commit_msg>fix filter url<commit_after>/*
 * MarketControl.cpp
 *
 *  Created on: Jun 11, 2017
 *      Author: ondra
 */

#include "marketControl.h"

#include <couchit/couchDB.h>
#include <couchit/exception.h>
#include <couchit/query.h>
#include <imtjson/rpc.h>
#include "../common/config.h"

namespace quark {

MarketControl::MarketControl(Value cfg, StrViewA dbname)
	:ordersDb(initCouchDBConfig(cfg,dbname,"-orders"))
	,tradesDb(initCouchDBConfig(cfg,dbname,"-trades"))
	,posDb(initCouchDBConfig(cfg,dbname,"-positions"))
	,orderControl(ordersDb)
{

}

static void notImpl(RpcRequest req) {
	req.setError(501,"Not implemented yet!");
}

bool MarketControl::testDatabase() {
	CouchDB::PConnection conn = ordersDb.getConnection("");
	try {
		ordersDb.requestGET(conn,nullptr,0);
		return true;
	} catch (const couchit::RequestError &e) {
		if (e.getCode() == 404) return false;
		throw;
	}
}

Value MarketControl::getMarketStatus()  {

	Value err = ordersDb.get("error",CouchDB::flgNullIfMissing);
	if (err == nullptr) {
		return Object("marketStatus","ok");
	} else {
		return Object("marketStatus","stopped")
				("reason",err);
	}

}

Value MarketControl::initRpc(RpcServer& rpcServer) {

	PMarketControl me = this;
	rpcServer.add("Order.create", me, &MarketControl::rpcOrderCreate);
	rpcServer.add("Order.modify", me, &MarketControl::rpcOrderUpdate);
	rpcServer.add("Order.cancel", me, &MarketControl::rpcOrderCancel);
	rpcServer.add("Order.get", me, &MarketControl::rpcOrderGet);
	rpcServer.add("Stream.orders",  me, &MarketControl::rpcStreamOrders);
	rpcServer.add("Stream.trades", me, &MarketControl::rpcStreamTrades);
	rpcServer.add("Stream.orderbook", me, &MarketControl::rpcStreamOrderbook);
	rpcServer.add("Stream.positions", me, &MarketControl::rpcStreamPositions);
	rpcServer.add("Stream.lastId", me, &MarketControl::rpcStreamLastId);
	rpcServer.add("Status.get", me, &MarketControl::rpcStatusGet);
	rpcServer.add("Status.clear", me, &MarketControl::rpcStatusClear);
	rpcServer.add("Orderbook.get",me, &MarketControl::rpcOrderbookGet);

	return getMarketStatus();

}

void MarketControl::rpcOrderCreate(RpcRequest rq) {
	static Value chkargs (json::array,{Object("%","any")});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.create(args[0]));
	} catch (ValidatonError &e) {
		rq.setError(400,"Validation failed", e.getError());
	}
}

void MarketControl::rpcOrderUpdate(RpcRequest rq) {
	static Value chkargs1 = {"string",Object("%","any")};
	static Value chkargs2 = {"string",Object("%","any"), "string"};
	Value args = rq.getArgs();
	try {
		if (rq.checkArgs(chkargs1)) {
			rq.setResult(orderControl.modify(args[0],args[1],json::undefined));
		} else if (rq.checkArgs(chkargs2)) {
			rq.setResult(orderControl.modify(args[0],args[1],args[2]));
		} else {
			rq.setArgError();
		}
	} catch (ValidatonError &e) {
		rq.setError(400,"Validation failed", e.getError());
	} catch (OrderNotFoundError &e) {
		rq.setError(404,"Order not found");
	} catch (ConflictError &e) {
		rq.setError(409,"Conflict",e.getActualDoc());
	}
}

void MarketControl::rpcOrderCancel(RpcRequest rq) {
	static Value chkargs (json::array,{"string"});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.cancel(args[0]));
	} catch (OrderNotFoundError &e) {
		rq.setError(404,"Order not found");
	}
}

void MarketControl::rpcOrderGet(RpcRequest rq) {
	static Value chkargs (json::array,{"string"});
	if (!rq.checkArgs(chkargs)) return rq.setArgError();
	Value args = rq.getArgs();
	try {
		rq.setResult(orderControl.getOrder(args[0]));
	} catch (const couchit::RequestError &e) {
		rq.setError(404,"Order not found");
	}
}

class MarketControl::BasicFeed: public FeedControl {
public:
	BasicFeed(couchit::CouchDB &db,
			  Value since,
			  RpcRequest rq,
			  String streamName)
				:FeedControl(db,since),rq(rq),streamName(streamName) {

	}
	virtual void init() override {
	}
	~BasicFeed() {
		stop();
	}

protected:
	RpcRequest rq;
	String streamName;
};

class MarketControl::OrderFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		static couchit::View initView("_design/index/_view/queue",couchit::View::includeDocs|couchit::View::update);
		initialView = &initView;
		feed.setFilter(couchit::Filter("index/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("id",doc["_id"])
				("_id",undefined)});
	}

};

class MarketControl::TradesFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		feed.setFilter(couchit::Filter("trades/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("id",doc["_id"])
				("_id",undefined)
				("_rev",undefined)
		});
	}

};

class MarketControl::PosFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		feed.setFilter(couchit::Filter("positions/stream",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		rq.sendNotify(streamName,{seqNum.toString(),
				Object(doc)
				("user",doc["_id"].getString().substr(2))
				("_id",undefined)
				("_rev",undefined)
		});
	}
};

class MarketControl::OrderbookFeed: public BasicFeed {
public:
	using BasicFeed::BasicFeed;
	virtual void init() override {
		static couchit::View initView("_design/index/_view/orderbook",couchit::View::includeDocs|couchit::View::update);
		this->initialView = &initView;
		feed.setFilter(couchit::Filter("index/orders",couchit::Filter::includeDocs));
	}
	virtual void onEvent(Value seqNum, Value doc) override {
		sendNotify(rq, streamName, doc, seqNum.toString());
	}
	static void sendNotify(RpcRequest &rq, StrViewA streamName, Value doc, Value seq) {
		Object ntf;
		bool finished = doc["finished"].getBool();
		rq.sendNotify(streamName,{seq,{doc["_id"],doc["dir"],doc["limitPrice"],finished?Value(0):doc["size"]}});
	}

};

void MarketControl::rpcStreamOrders(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		ordersFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		ordersFeed = new OrderFeed(ordersDb, since, rq, "order");
		ordersFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamTrades(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		tradesFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		tradesFeed = new TradesFeed(tradesDb, since, rq, "trade");
		tradesFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamPositions(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		posFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		posFeed = new PosFeed(posDb, since, rq, "position");
		posFeed->start();
		rq.setResult(true);

	} else {
		rq.setArgError();
	}
}

void MarketControl::rpcStreamOrderbook(RpcRequest rq) {
	static Value turnOffArgs = Value(json::array,{false});
	static Value turnOnArgs = {true,{"string","optional"} };
	if (rq.checkArgs(turnOffArgs)) {

		orderbookFeed = nullptr;
		rq.setResult(true);

	} else if (rq.checkArgs(turnOnArgs)) {
		Value since = rq.getArgs()[1];
		orderbookFeed = new OrderbookFeed(ordersDb, since, rq, "orderbook");
		orderbookFeed->start();
		rq.setResult(true);
	} else {
		rq.setArgError();
	}
}

void MarketControl::FeedControl::stop() {

	if (!stopped) {
		feed.cancelWait();
		thr.join();
		stopped = true;
	}
}

void MarketControl::FeedControl::start() {
	bool initWait = false;
	using namespace couchit;
	std::condition_variable initWaitCond;
	std::mutex lock;

	thr = std::thread([&]{

		init();

		{
		std::unique_lock<std::mutex> _(lock);
		initWait = true;
		initWaitCond.notify_all();
		}

		Value lastDoc;
		if (!since.defined() && initialView != nullptr)
		{
			Query q = db.createQuery(*initialView);
			Result r = q.exec();
			for (Row rw : r) {
				onEvent(r.getUpdateSeq(),rw.doc);
				lastDoc = rw.doc;
			}
			since = r.getUpdateSeq();
		}

		if (since.defined())
			feed.since(since);
		try {
			feed >> [&](ChangedDoc x) {
				if (x.doc == lastDoc) return true;
				lastDoc = json::undefined;
				onEvent(x.seqId, x.doc);
				return true;
			};
		} catch (couchit::CanceledException &) {

		}
	});

	std::unique_lock<std::mutex> _(lock);
	initWaitCond.wait(_,[&]{return initWait;});
	stopped = false;
}

MarketControl::FeedControl::FeedControl(CouchDB& db, Value since)
	:feed(db.createChangesFeed()),  since(since), db(db), stopped(true)
{
	feed.setTimeout(-1);
	feed.includeDocs(true);
}

void MarketControl::rpcStreamLastId(RpcRequest rq) {
	if (!rq.checkArgs(json::array)) return rq.setArgError();

	rq.setResult(Object("orders",ordersDb.getLastSeqNumber())
					   ("trades",tradesDb.getLastSeqNumber())
					   ("positions",posDb.getLastSeqNumber())
			);

}

void quark::MarketControl::rpcStatusGet(RpcRequest rq) {
	rq.setResult(getMarketStatus());
}

void quark::MarketControl::rpcStatusClear(RpcRequest rq) {
	couchit::Document doc = ordersDb.get("error");
	doc.setDeleted();
	ordersDb.put(doc);
	rq.setResult(getMarketStatus());
}

void quark::MarketControl::rpcOrderbookGet(RpcRequest rq) {
	couchit::View orderbookView("_design/index/_view/orderbook",couchit::View::update);
	couchit::Result res = ordersDb.createQuery(orderbookView).exec();
	Array out;
	for (couchit::Row rw : res) {
		out.push_back({rw["id"],rw.key[0], rw.key[1], rw.value});
	}
	rq.setResult(out);
}

}

/* namespace quark */

<|endoftext|>


<commit_before>/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.cpp
**
** -------------------------------------------------------------------------*/

#ifdef HAVE_LIVE555

#include "rtc_base/timeutils.h"
#include "rtc_base/logging.h"
#include "rtc_base/optional.h"

#include "modules/video_coding/h264_sprop_parameter_sets.h"
#include "api/video/i420_buffer.h"
#include "common_video/libyuv/include/webrtc_libyuv.h"

#include "libyuv/convert.h"

#include "rtspvideocapturer.h"

uint8_t marker[] = { 0, 0, 0, 1};

int decodeRTPTransport(const std::string & rtpTransportString)
{
	int rtptransport = RTSPConnection::RTPUDPUNICAST;
	if (rtpTransportString == "tcp") {
		rtptransport = RTSPConnection::RTPOVERTCP;
	} else if (rtpTransportString == "http") {
		rtptransport = RTSPConnection::RTPOVERHTTP;
	} else if (rtpTransportString == "multicast") {
		rtptransport = RTSPConnection::RTPUDPMULTICAST;
	}
	return rtptransport;
}

RTSPVideoCapturer::RTSPVideoCapturer(const std::string & uri, int timeout, const std::string & rtptransport) : m_connection(m_env, this, uri.c_str(), timeout, decodeRTPTransport(rtptransport), 1)
{
	LOG(INFO) << "RTSPVideoCapturer" << uri ;
	m_h264 = h264_new();
}

RTSPVideoCapturer::~RTSPVideoCapturer()
{
	h264_free(m_h264);
}

bool RTSPVideoCapturer::onNewSession(const char* id,const char* media, const char* codec, const char* sdp)
{
	LOG(INFO) << "RTSPVideoCapturer::onNewSession " << media << "/" << codec << " " << sdp;
	bool success = false;
	if ( (strcmp(media, "video") == 0) && (strcmp(codec, "H264") == 0) )
	{
		m_codec = codec;
		const char* pattern="sprop-parameter-sets=";
		const char* sprop=strstr(sdp, pattern);
		if (sprop)
		{
			std::string sdpstr(sprop+strlen(pattern));
			size_t pos = sdpstr.find_first_of(" ;\r\n");
			if (pos != std::string::npos)
			{
				sdpstr.erase(pos);
			}
			webrtc::H264SpropParameterSets sprops;
			if (sprops.DecodeSprop(sdpstr))
			{
				struct timeval presentationTime;
				timerclear(&presentationTime);

				std::vector<uint8_t> sps;
				sps.insert(sps.end(), marker, marker+sizeof(marker));
				sps.insert(sps.end(), sprops.sps_nalu().begin(), sprops.sps_nalu().end());
				onData(id, sps.data(), sps.size(), presentationTime);

				std::vector<uint8_t> pps;
				pps.insert(pps.end(), marker, marker+sizeof(marker));
				pps.insert(pps.end(), sprops.pps_nalu().begin(), sprops.pps_nalu().end());
				onData(id, pps.data(), pps.size(), presentationTime);
			}
			else
			{
				LOG(WARNING) << "Cannot decode SPS:" << sprop;
			}
		}
		success = true;
	}
	else if ( (strcmp(media, "video") == 0) && (strcmp(codec, "JPEG") == 0) )
	{
		m_codec = codec;
		success = true;
	}
	return success;
}

bool RTSPVideoCapturer::onData(const char* id, unsigned char* buffer, ssize_t size, struct timeval presentationTime)
{
	int64_t ts = presentationTime.tv_sec;
	ts = ts*1000 + presentationTime.tv_usec/1000;
	LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData size:" << size << " ts:" << ts;
	int res = 0;

	if (m_codec == "H264") {
		int nal_start = 0;
		int nal_end   = 0;
		find_nal_unit(buffer, size, &nal_start, &nal_end);
		read_nal_unit(m_h264, &buffer[nal_start], nal_end - nal_start);
		if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_SPS) {
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SPS";
			m_cfg.clear();
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);

			unsigned int width = ((m_h264->sps->pic_width_in_mbs_minus1 +1)*16) - m_h264->sps->frame_crop_left_offset*2 - m_h264->sps->frame_crop_right_offset*2;
			unsigned int height= ((2 - m_h264->sps->frame_mbs_only_flag)* (m_h264->sps->pic_height_in_map_units_minus1 +1) * 16) - (m_h264->sps->frame_crop_top_offset * 2) - (m_h264->sps->frame_crop_bottom_offset * 2);
			unsigned int fps=25;
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SPS set timing_info_present_flag:" << m_h264->sps->vui.timing_info_present_flag << " " << m_h264->sps->vui.time_scale << " " << m_h264->sps->vui.num_units_in_tick;
			if (m_decoder.get()) {
				if ( (GetCaptureFormat()->width != width) || (GetCaptureFormat()->height != height) )  {
					LOG(INFO) << "format changed => set format from " << GetCaptureFormat()->width << "x" << GetCaptureFormat()->height	 << " to " << width << "x" << height;
					m_decoder.reset(NULL);
				}
			}

			if (!m_decoder.get()) {
				LOG(INFO) << "RTSPVideoCapturer:onData SPS set format " << width << "x" << height << " fps:" << fps;
				cricket::VideoFormat videoFormat(width, height, cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_I420);
				SetCaptureFormat(&videoFormat);

				m_decoder.reset(m_factory.CreateVideoDecoder(webrtc::VideoCodecType::kVideoCodecH264));
				webrtc::VideoCodec codec_settings;
				codec_settings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
				m_decoder->InitDecode(&codec_settings,2);
				m_decoder->RegisterDecodeCompleteCallback(this);
			}
		}
		else if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_PPS) {
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData PPS";
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);
		}
		else if (m_decoder.get()) {
			if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_CODED_SLICE_IDR) {
				LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData IDR";
				uint8_t buf[m_cfg.size() + size];
				memcpy(buf, m_cfg.data(), m_cfg.size());
				memcpy(buf+m_cfg.size(), buffer, size);
				webrtc::EncodedImage input_image(buf, sizeof(buf), sizeof(buf) + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				input_image._timeStamp = ts*1000;
				res = m_decoder->Decode(input_image, false, NULL);
			}
			else {
				LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SLICE NALU:" << m_h264->nal->nal_unit_type;
				webrtc::EncodedImage input_image(buffer, size, size + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				input_image._timeStamp = ts*1000;
				res = m_decoder->Decode(input_image, false, NULL);
			}
		} else {
			LOG(LS_ERROR) << "RTSPVideoCapturer:onData no decoder";
			res = -1;
		}
	} else if (m_codec == "JPEG") {
		int32_t width = 0;
		int32_t height = 0;
		if (libyuv::MJPGSize(buffer, size, &width, &height) == 0) {
			int stride_y = width;
			int stride_uv = (width + 1) / 2;

			rtc::scoped_refptr<webrtc::I420Buffer> I420buffer = webrtc::I420Buffer::Create(width, height, stride_y, stride_uv, stride_uv);
			const int conversionResult = ConvertToI420(webrtc::VideoType::kMJPEG, buffer, 0, 0,
									width, height, size,
									webrtc::kVideoRotation_0, I420buffer.get());
			if (conversionResult >= 0) {
				webrtc::VideoFrame frame(I420buffer, 0, ts*1000, webrtc::kVideoRotation_0);
				this->Decoded(frame);
			} else {
				LOG(LS_ERROR) << "RTSPVideoCapturer:onData decoder error:" << conversionResult;
				res = -1;
			}
		} else {
			LOG(LS_ERROR) << "RTSPVideoCapturer:onData cannot JPEG dimension";
			res = -1;
		}

	}

	return (res == 0);
}

ssize_t RTSPVideoCapturer::onNewBuffer(unsigned char* buffer, ssize_t size)
{
	ssize_t markerSize = 0;
	if (m_codec == "H264") {
		if (size > sizeof(marker))
		{
			memcpy( buffer, marker, sizeof(marker) );
			markerSize = sizeof(marker);
		}
	}
	return 	markerSize;
}

int32_t RTSPVideoCapturer::Decoded(webrtc::VideoFrame& decodedImage)
{
	if (decodedImage.timestamp_us() == 0) {
		decodedImage.set_timestamp_us(decodedImage.timestamp());
	}
	LOG(LS_VERBOSE) << "RTSPVideoCapturer::Decoded " << decodedImage.size() << " " << decodedImage.timestamp_us() << " " << decodedImage.timestamp() << " " << decodedImage.ntp_time_ms() << " " << decodedImage.render_time_ms();
	this->OnFrame(decodedImage, decodedImage.height(), decodedImage.width());
	return true;
}

cricket::CaptureState RTSPVideoCapturer::Start(const cricket::VideoFormat& format)
{
	SetCaptureFormat(&format);
	SetCaptureState(cricket::CS_RUNNING);
	rtc::Thread::Start();
	return cricket::CS_RUNNING;
}

void RTSPVideoCapturer::Stop()
{
	m_env.stop();
	rtc::Thread::Stop();
	SetCaptureFormat(NULL);
	SetCaptureState(cricket::CS_STOPPED);
}

void RTSPVideoCapturer::Run()
{
	m_env.mainloop();
}

bool RTSPVideoCapturer::GetPreferredFourccs(std::vector<unsigned int>* fourccs)
{
	return true;
}
#endif
<commit_msg>fix build: remove unused include<commit_after>/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.cpp
**
** -------------------------------------------------------------------------*/

#ifdef HAVE_LIVE555

#include "rtc_base/timeutils.h"
#include "rtc_base/logging.h"

#include "modules/video_coding/h264_sprop_parameter_sets.h"
#include "api/video/i420_buffer.h"
#include "common_video/libyuv/include/webrtc_libyuv.h"

#include "libyuv/convert.h"

#include "rtspvideocapturer.h"

uint8_t marker[] = { 0, 0, 0, 1};

int decodeRTPTransport(const std::string & rtpTransportString)
{
	int rtptransport = RTSPConnection::RTPUDPUNICAST;
	if (rtpTransportString == "tcp") {
		rtptransport = RTSPConnection::RTPOVERTCP;
	} else if (rtpTransportString == "http") {
		rtptransport = RTSPConnection::RTPOVERHTTP;
	} else if (rtpTransportString == "multicast") {
		rtptransport = RTSPConnection::RTPUDPMULTICAST;
	}
	return rtptransport;
}

RTSPVideoCapturer::RTSPVideoCapturer(const std::string & uri, int timeout, const std::string & rtptransport) : m_connection(m_env, this, uri.c_str(), timeout, decodeRTPTransport(rtptransport), 1)
{
	LOG(INFO) << "RTSPVideoCapturer" << uri ;
	m_h264 = h264_new();
}

RTSPVideoCapturer::~RTSPVideoCapturer()
{
	h264_free(m_h264);
}

bool RTSPVideoCapturer::onNewSession(const char* id,const char* media, const char* codec, const char* sdp)
{
	LOG(INFO) << "RTSPVideoCapturer::onNewSession " << media << "/" << codec << " " << sdp;
	bool success = false;
	if ( (strcmp(media, "video") == 0) && (strcmp(codec, "H264") == 0) )
	{
		m_codec = codec;
		const char* pattern="sprop-parameter-sets=";
		const char* sprop=strstr(sdp, pattern);
		if (sprop)
		{
			std::string sdpstr(sprop+strlen(pattern));
			size_t pos = sdpstr.find_first_of(" ;\r\n");
			if (pos != std::string::npos)
			{
				sdpstr.erase(pos);
			}
			webrtc::H264SpropParameterSets sprops;
			if (sprops.DecodeSprop(sdpstr))
			{
				struct timeval presentationTime;
				timerclear(&presentationTime);

				std::vector<uint8_t> sps;
				sps.insert(sps.end(), marker, marker+sizeof(marker));
				sps.insert(sps.end(), sprops.sps_nalu().begin(), sprops.sps_nalu().end());
				onData(id, sps.data(), sps.size(), presentationTime);

				std::vector<uint8_t> pps;
				pps.insert(pps.end(), marker, marker+sizeof(marker));
				pps.insert(pps.end(), sprops.pps_nalu().begin(), sprops.pps_nalu().end());
				onData(id, pps.data(), pps.size(), presentationTime);
			}
			else
			{
				LOG(WARNING) << "Cannot decode SPS:" << sprop;
			}
		}
		success = true;
	}
	else if ( (strcmp(media, "video") == 0) && (strcmp(codec, "JPEG") == 0) )
	{
		m_codec = codec;
		success = true;
	}
	return success;
}

bool RTSPVideoCapturer::onData(const char* id, unsigned char* buffer, ssize_t size, struct timeval presentationTime)
{
	int64_t ts = presentationTime.tv_sec;
	ts = ts*1000 + presentationTime.tv_usec/1000;
	LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData size:" << size << " ts:" << ts;
	int res = 0;

	if (m_codec == "H264") {
		int nal_start = 0;
		int nal_end   = 0;
		find_nal_unit(buffer, size, &nal_start, &nal_end);
		read_nal_unit(m_h264, &buffer[nal_start], nal_end - nal_start);
		if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_SPS) {
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SPS";
			m_cfg.clear();
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);

			unsigned int width = ((m_h264->sps->pic_width_in_mbs_minus1 +1)*16) - m_h264->sps->frame_crop_left_offset*2 - m_h264->sps->frame_crop_right_offset*2;
			unsigned int height= ((2 - m_h264->sps->frame_mbs_only_flag)* (m_h264->sps->pic_height_in_map_units_minus1 +1) * 16) - (m_h264->sps->frame_crop_top_offset * 2) - (m_h264->sps->frame_crop_bottom_offset * 2);
			unsigned int fps=25;
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SPS set timing_info_present_flag:" << m_h264->sps->vui.timing_info_present_flag << " " << m_h264->sps->vui.time_scale << " " << m_h264->sps->vui.num_units_in_tick;
			if (m_decoder.get()) {
				if ( (GetCaptureFormat()->width != width) || (GetCaptureFormat()->height != height) )  {
					LOG(INFO) << "format changed => set format from " << GetCaptureFormat()->width << "x" << GetCaptureFormat()->height	 << " to " << width << "x" << height;
					m_decoder.reset(NULL);
				}
			}

			if (!m_decoder.get()) {
				LOG(INFO) << "RTSPVideoCapturer:onData SPS set format " << width << "x" << height << " fps:" << fps;
				cricket::VideoFormat videoFormat(width, height, cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_I420);
				SetCaptureFormat(&videoFormat);

				m_decoder.reset(m_factory.CreateVideoDecoder(webrtc::VideoCodecType::kVideoCodecH264));
				webrtc::VideoCodec codec_settings;
				codec_settings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
				m_decoder->InitDecode(&codec_settings,2);
				m_decoder->RegisterDecodeCompleteCallback(this);
			}
		}
		else if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_PPS) {
			LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData PPS";
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);
		}
		else if (m_decoder.get()) {
			if (m_h264->nal->nal_unit_type == NAL_UNIT_TYPE_CODED_SLICE_IDR) {
				LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData IDR";
				uint8_t buf[m_cfg.size() + size];
				memcpy(buf, m_cfg.data(), m_cfg.size());
				memcpy(buf+m_cfg.size(), buffer, size);
				webrtc::EncodedImage input_image(buf, sizeof(buf), sizeof(buf) + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				input_image._timeStamp = ts*1000;
				res = m_decoder->Decode(input_image, false, NULL);
			}
			else {
				LOG(LS_VERBOSE) << "RTSPVideoCapturer:onData SLICE NALU:" << m_h264->nal->nal_unit_type;
				webrtc::EncodedImage input_image(buffer, size, size + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				input_image._timeStamp = ts*1000;
				res = m_decoder->Decode(input_image, false, NULL);
			}
		} else {
			LOG(LS_ERROR) << "RTSPVideoCapturer:onData no decoder";
			res = -1;
		}
	} else if (m_codec == "JPEG") {
		int32_t width = 0;
		int32_t height = 0;
		if (libyuv::MJPGSize(buffer, size, &width, &height) == 0) {
			int stride_y = width;
			int stride_uv = (width + 1) / 2;

			rtc::scoped_refptr<webrtc::I420Buffer> I420buffer = webrtc::I420Buffer::Create(width, height, stride_y, stride_uv, stride_uv);
			const int conversionResult = ConvertToI420(webrtc::VideoType::kMJPEG, buffer, 0, 0,
									width, height, size,
									webrtc::kVideoRotation_0, I420buffer.get());
			if (conversionResult >= 0) {
				webrtc::VideoFrame frame(I420buffer, 0, ts*1000, webrtc::kVideoRotation_0);
				this->Decoded(frame);
			} else {
				LOG(LS_ERROR) << "RTSPVideoCapturer:onData decoder error:" << conversionResult;
				res = -1;
			}
		} else {
			LOG(LS_ERROR) << "RTSPVideoCapturer:onData cannot JPEG dimension";
			res = -1;
		}

	}

	return (res == 0);
}

ssize_t RTSPVideoCapturer::onNewBuffer(unsigned char* buffer, ssize_t size)
{
	ssize_t markerSize = 0;
	if (m_codec == "H264") {
		if (size > sizeof(marker))
		{
			memcpy( buffer, marker, sizeof(marker) );
			markerSize = sizeof(marker);
		}
	}
	return 	markerSize;
}

int32_t RTSPVideoCapturer::Decoded(webrtc::VideoFrame& decodedImage)
{
	if (decodedImage.timestamp_us() == 0) {
		decodedImage.set_timestamp_us(decodedImage.timestamp());
	}
	LOG(LS_VERBOSE) << "RTSPVideoCapturer::Decoded " << decodedImage.size() << " " << decodedImage.timestamp_us() << " " << decodedImage.timestamp() << " " << decodedImage.ntp_time_ms() << " " << decodedImage.render_time_ms();
	this->OnFrame(decodedImage, decodedImage.height(), decodedImage.width());
	return true;
}

cricket::CaptureState RTSPVideoCapturer::Start(const cricket::VideoFormat& format)
{
	SetCaptureFormat(&format);
	SetCaptureState(cricket::CS_RUNNING);
	rtc::Thread::Start();
	return cricket::CS_RUNNING;
}

void RTSPVideoCapturer::Stop()
{
	m_env.stop();
	rtc::Thread::Stop();
	SetCaptureFormat(NULL);
	SetCaptureState(cricket::CS_STOPPED);
}

void RTSPVideoCapturer::Run()
{
	m_env.mainloop();
}

bool RTSPVideoCapturer::GetPreferredFourccs(std::vector<unsigned int>* fourccs)
{
	return true;
}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file runner/interpreter.cc
 ** \brief Implementation of runner::Interpreter.
 */

// #define ENABLE_DEBUG_TRACES

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

#include <libport/compiler.hh>
#include <libport/config.h>
#include <libport/finally.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#include <libport/lexical-cast.hh>
#include <libport/symbol.hh>

#include <ast/call.hh>
#include <ast/exp.hh>

#include <kernel/uconnection.hh>

#include <object/symbols.hh>
#include <object/urbi-exception.hh>
#include <object/system.hh>

#include <parser/uparser.hh>

#include <runner/interpreter.hh>
#include <urbi/runner/raise.hh>

#include <sched/exception.hh>

#include <urbi/object/cxx-conversions.hh>
#include <urbi/object/global.hh>
#include <urbi/object/lobby.hh>
#include <urbi/object/location.hh>
#include <urbi/object/job.hh>

namespace runner
{
  using libport::Finally;

  // This function takes an expression and attempts to decompose it
  // into a list of identifiers. The resulting chain is stored in
  // reverse order, that is the most specific tag first.
  typedef std::vector<libport::Symbol> tag_chain_type;
  static
  tag_chain_type
  decompose_tag_chain (ast::rConstExp e)
  {
    tag_chain_type res;
    while (!e->implicit())
    {
      ast::rConstCall c = e.unsafe_cast<const ast::Call>();
      if (!c || c->arguments_get())
	runner::raise_urbi(SYMBOL(ImplicitTagComponent));
      res.push_back (c->name_get());
      e = c->target_get();
    }
    return res;
  }

  /*--------------.
  | Interpreter.  |
  `--------------*/

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           ast::rConstAst ast,
                           const libport::Symbol& name)
    : Runner(lobby, sched, name)
    , ast_(ast)
    , code_(0)
    , result_(0)
    , stacks_(lobby)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           rObject code,
                           const libport::Symbol& name,
                           rObject self,
                           const objects_type& args)
    : Runner(lobby, sched, name)
    , ast_(0)
    , code_(code)
    , self_(self)
    , args_(args)
    , result_(0)
    , stacks_(lobby)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::Interpreter(const Interpreter& model, rObject code,
			   const libport::Symbol& name,
                           const objects_type& args)
    : Runner(model, name)
    , ast_(0)
    , code_(code)
    , args_(args)
    , result_(0)
    , call_stack_(model.call_stack_)
    , stacks_(model.lobby_)
  {
    tag_stack_set(model.tag_stack_get_all());
    init();
  }

  Interpreter::Interpreter(const Interpreter& model,
			   ast::rConstAst ast,
			   const libport::Symbol& name)
    : Runner(model, name)
    , ast_(ast)
    , code_(0)
    , result_(0)
    , stacks_(model.lobby_)
  {
    tag_stack_set(model.tag_stack_get_all());
    init();
  }

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           boost::function0<void> job,
                           rObject self,
                           const libport::Symbol& name)
    : Runner(lobby, sched, name)
    , ast_(0)
    , code_(0)
    , job_(job)
    , result_(0)
    , stacks_(self)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::~Interpreter()
  {
  }

  void
  Interpreter::init()
  {
    // Push a dummy scope tag, in case we do have an "at" at the
    // toplevel.
    create_scope_tag();
  }

  void
  Interpreter::show_exception(object::UrbiException& ue)
  {
    send_message("error",
                 libport::format("!!! %s",
                                 (ue.value_get()
                                  ->call(SYMBOL(asString))
                                  ->as<object::String>()
                                  ->value_get())));
    show_backtrace(ue.backtrace_get(), "error");
  }

  void
  Interpreter::work()
  {
    try
    {
      aver(ast_ || code_ || job_);
      check_for_pending_exception();
      if (ast_)
	result_ = operator()(ast_.get());
      else if (code_)
      {
        libport::push_front(args_, self_ ? self_ : rObject(lobby_));
	result_ = apply(code_, libport::Symbol::make_empty(), args_);
      }
      else
        job_();
    }
    catch (object::UrbiException& exn)
    {
      // If this runner has a parent, let the exception go through
      // so that it will be handled by Job::run().
      if (child_job())
	throw;
      else
      // This is a detached runner, show the error.
      {
        // Yielding inside a catch is forbidden.
        Finally finally(boost::bind(&Runner::non_interruptible_set,
                                    this, non_interruptible_get()));
        non_interruptible_set(true);
        show_exception(exn);
      }
    }
  }

  void
  Interpreter::scheduling_error(const std::string& msg)
  {
    libport::Finally finally;
    sched::Job::Collector collector(this);
    // We may have a situation here. If the stack space is running
    // near exhaustion, we cannot reasonably hope that we will get
    // enough stack space to build an exception, which potentially
    // requires a non-negligible amount of calls. For this reason, we
    // create another job whose job is to build the exception (in a
    // freshly allocated stack) and propagate it to us as we are its
    // parent.
    CAPTURE_GLOBAL(Exception);
    object::rObject Scheduling = Exception->slot_get(SYMBOL(Scheduling));
    if (non_interruptible_get())
    { // The user requested non-interruptible mode for a reason, honor it
      // and try to throw in this job.
      Scheduling->call(SYMBOL(throwNew), object::to_urbi(msg));
      return;
    }

    object::objects_type args;
    args << object::to_urbi(msg);
    sched::rJob child =
      new Interpreter(*this,
                      Scheduling->slot_get(SYMBOL(throwNew)),
                      SYMBOL(Scheduling),
                      args);
    register_child(child, collector);
    child->start_job();

    try
    {
      yield_until_terminated(*child);
    }
    catch (const sched::ChildException& ce)
    {
      try
      {
	ce.rethrow_child_exception();
      }
      catch (const object::UrbiException& ue)
      {
	raise(ue.value_get(), false);
      }
    }
  }

  object::rObject
  Interpreter::eval_tag(ast::rConstExp e)
  {
    try
    {
      // Try to evaluate e as a normal expression.
      return operator()(e.get());
    }
    catch (object::UrbiException&)
    {
      LIBPORT_DEBUG("Implicit tag: " << *e);
      // We got a lookup error. It means that we have to automatically
      // create the tag. In this case, we only accept k1 style tags,
      // i.e. chains of identifiers, excluding function calls.
      // The reason to do that is:
      //   - we do not want to mix k1 non-declared syntax with k2
      //     clean syntax for tags
      //   - we have no way to know whether the lookup error arrived
      //     in a function call or during the direct resolution of
      //     the name.

      // `Tag.tags' represents the top level tag.
      CAPTURE_GLOBAL2(Tag, tags);
      rObject parent = tags;
      rObject where = stacks_.self();
      tag_chain_type chain = decompose_tag_chain(e);
      rforeach (const libport::Symbol& elt, chain)
      {
	// Check whether the concerned level in the chain already
	// exists.
	if (rObject owner = where->slot_locate(elt).first)
        {
          LIBPORT_DEBUG("Component " << elt << " exists.");
	  where = owner->local_slot_get(elt)->value();
	  if (object::Tag* parent_ = dynamic_cast<object::Tag*>(where.get()))
	  {
            LIBPORT_DEBUG("It is a tag, so use it as the new parent.");
	    parent = parent_;
	  }
        }
	else
	{
	  // We have to create a new tag, which will be attached
	  // to the upper level (hierarchical tags, implicitly
	  // rooted by Tags).
	  where = parent->call(SYMBOL(new), new object::String(elt));
	  parent->slot_set(elt, where);
	  parent = where;
	}
      }

      return where;
    }
  }

  void
  Interpreter::show_backtrace(const call_stack_type& bt,
                              const std::string& chan)
  {
    rforeach (const call_type& c, bt)
    {
      std::ostringstream o;
      o << "!!!    called from: " << c;
      send_message(chan, o.str());
    }
  }

  void
  Interpreter::show_backtrace(const std::string& chan)
  {
    show_backtrace(call_stack_, chan);
  }

  Interpreter::backtrace_type
  Interpreter::backtrace_get() const
  {
    CAPTURE_GLOBAL(StackFrame);
    backtrace_type res;
    foreach (call_type c, call_stack_)
    {
      rObject loc = object::nil_class;
      if (c.second)
        loc = new object::Location(c.second.get());
      rObject frame =
        StackFrame
        ->call("new", new object::String(c.first.name_get()), loc);
      res.push_back(frame_type(frame));
    }
    return res;
  }

  object::call_stack_type
  Interpreter::call_stack_get() const
  {
    return call_stack_;
  }

  void
  Interpreter::raise(rObject exn, bool skip_last)
  {
    CAPTURE_GLOBAL(Exception);

    // innermost_node_ can be empty is the interpreter has not interpreted
    // any urbiscript.  i-e: slot_set can raise an exception only from the
    // C++ side.  Best would be to produce a C++ backtrace instead.
    if (is_a(exn, Exception) && !innermost_node_)
    {
      boost::optional<ast::loc> l;
      if (object::is_system_location(innermost_node_->location_get()))
      {
        rforeach(const call_type& c, call_stack_get())
          if (c.second)
          {
            l = c.second;
            break;
          }
      }
      else
        l = innermost_node_->location_get();
      if (l)
        exn->slot_update(SYMBOL(location),
                         new object::String(string_cast(*l)));
      exn->slot_update(SYMBOL(backtrace),
                       as_job()->as<object::Job>()->backtrace());
    }
    call_stack_type bt = call_stack_get();
    if (skip_last && !bt.empty())
      bt.pop_back();
    throw object::UrbiException(exn, bt);
  }

} // namespace runner

// If not in speed mode, compile visit methods here.
#ifndef LIBPORT_COMPILATION_MODE_SPEED
# include <runner/interpreter-visit.hxx>
#endif
<commit_msg>Fix exception backtrace (inversed condition).<commit_after>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file runner/interpreter.cc
 ** \brief Implementation of runner::Interpreter.
 */

// #define ENABLE_DEBUG_TRACES

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

#include <libport/compiler.hh>
#include <libport/config.h>
#include <libport/finally.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#include <libport/lexical-cast.hh>
#include <libport/symbol.hh>

#include <ast/call.hh>
#include <ast/exp.hh>

#include <kernel/uconnection.hh>

#include <object/symbols.hh>
#include <object/urbi-exception.hh>
#include <object/system.hh>

#include <parser/uparser.hh>

#include <runner/interpreter.hh>
#include <urbi/runner/raise.hh>

#include <sched/exception.hh>

#include <urbi/object/cxx-conversions.hh>
#include <urbi/object/global.hh>
#include <urbi/object/lobby.hh>
#include <urbi/object/location.hh>
#include <urbi/object/job.hh>

namespace runner
{
  using libport::Finally;

  // This function takes an expression and attempts to decompose it
  // into a list of identifiers. The resulting chain is stored in
  // reverse order, that is the most specific tag first.
  typedef std::vector<libport::Symbol> tag_chain_type;
  static
  tag_chain_type
  decompose_tag_chain (ast::rConstExp e)
  {
    tag_chain_type res;
    while (!e->implicit())
    {
      ast::rConstCall c = e.unsafe_cast<const ast::Call>();
      if (!c || c->arguments_get())
	runner::raise_urbi(SYMBOL(ImplicitTagComponent));
      res.push_back (c->name_get());
      e = c->target_get();
    }
    return res;
  }

  /*--------------.
  | Interpreter.  |
  `--------------*/

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           ast::rConstAst ast,
                           const libport::Symbol& name)
    : Runner(lobby, sched, name)
    , ast_(ast)
    , code_(0)
    , result_(0)
    , stacks_(lobby)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           rObject code,
                           const libport::Symbol& name,
                           rObject self,
                           const objects_type& args)
    : Runner(lobby, sched, name)
    , ast_(0)
    , code_(code)
    , self_(self)
    , args_(args)
    , result_(0)
    , stacks_(lobby)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::Interpreter(const Interpreter& model, rObject code,
			   const libport::Symbol& name,
                           const objects_type& args)
    : Runner(model, name)
    , ast_(0)
    , code_(code)
    , args_(args)
    , result_(0)
    , call_stack_(model.call_stack_)
    , stacks_(model.lobby_)
  {
    tag_stack_set(model.tag_stack_get_all());
    init();
  }

  Interpreter::Interpreter(const Interpreter& model,
			   ast::rConstAst ast,
			   const libport::Symbol& name)
    : Runner(model, name)
    , ast_(ast)
    , code_(0)
    , result_(0)
    , stacks_(model.lobby_)
  {
    tag_stack_set(model.tag_stack_get_all());
    init();
  }

  Interpreter::Interpreter(rLobby lobby,
                           sched::Scheduler& sched,
                           boost::function0<void> job,
                           rObject self,
                           const libport::Symbol& name)
    : Runner(lobby, sched, name)
    , ast_(0)
    , code_(0)
    , job_(job)
    , result_(0)
    , stacks_(self)
  {
    init();
    apply_tag(lobby->slot_get(SYMBOL(connectionTag))->as<object::Tag>(), 0);
  }

  Interpreter::~Interpreter()
  {
  }

  void
  Interpreter::init()
  {
    // Push a dummy scope tag, in case we do have an "at" at the
    // toplevel.
    create_scope_tag();
  }

  void
  Interpreter::show_exception(object::UrbiException& ue)
  {
    send_message("error",
                 libport::format("!!! %s",
                                 (ue.value_get()
                                  ->call(SYMBOL(asString))
                                  ->as<object::String>()
                                  ->value_get())));
    show_backtrace(ue.backtrace_get(), "error");
  }

  void
  Interpreter::work()
  {
    try
    {
      aver(ast_ || code_ || job_);
      check_for_pending_exception();
      if (ast_)
	result_ = operator()(ast_.get());
      else if (code_)
      {
        libport::push_front(args_, self_ ? self_ : rObject(lobby_));
	result_ = apply(code_, libport::Symbol::make_empty(), args_);
      }
      else
        job_();
    }
    catch (object::UrbiException& exn)
    {
      // If this runner has a parent, let the exception go through
      // so that it will be handled by Job::run().
      if (child_job())
	throw;
      else
      // This is a detached runner, show the error.
      {
        // Yielding inside a catch is forbidden.
        Finally finally(boost::bind(&Runner::non_interruptible_set,
                                    this, non_interruptible_get()));
        non_interruptible_set(true);
        show_exception(exn);
      }
    }
  }

  void
  Interpreter::scheduling_error(const std::string& msg)
  {
    libport::Finally finally;
    sched::Job::Collector collector(this);
    // We may have a situation here. If the stack space is running
    // near exhaustion, we cannot reasonably hope that we will get
    // enough stack space to build an exception, which potentially
    // requires a non-negligible amount of calls. For this reason, we
    // create another job whose job is to build the exception (in a
    // freshly allocated stack) and propagate it to us as we are its
    // parent.
    CAPTURE_GLOBAL(Exception);
    object::rObject Scheduling = Exception->slot_get(SYMBOL(Scheduling));
    if (non_interruptible_get())
    { // The user requested non-interruptible mode for a reason, honor it
      // and try to throw in this job.
      Scheduling->call(SYMBOL(throwNew), object::to_urbi(msg));
      return;
    }

    object::objects_type args;
    args << object::to_urbi(msg);
    sched::rJob child =
      new Interpreter(*this,
                      Scheduling->slot_get(SYMBOL(throwNew)),
                      SYMBOL(Scheduling),
                      args);
    register_child(child, collector);
    child->start_job();

    try
    {
      yield_until_terminated(*child);
    }
    catch (const sched::ChildException& ce)
    {
      try
      {
	ce.rethrow_child_exception();
      }
      catch (const object::UrbiException& ue)
      {
	raise(ue.value_get(), false);
      }
    }
  }

  object::rObject
  Interpreter::eval_tag(ast::rConstExp e)
  {
    try
    {
      // Try to evaluate e as a normal expression.
      return operator()(e.get());
    }
    catch (object::UrbiException&)
    {
      LIBPORT_DEBUG("Implicit tag: " << *e);
      // We got a lookup error. It means that we have to automatically
      // create the tag. In this case, we only accept k1 style tags,
      // i.e. chains of identifiers, excluding function calls.
      // The reason to do that is:
      //   - we do not want to mix k1 non-declared syntax with k2
      //     clean syntax for tags
      //   - we have no way to know whether the lookup error arrived
      //     in a function call or during the direct resolution of
      //     the name.

      // `Tag.tags' represents the top level tag.
      CAPTURE_GLOBAL2(Tag, tags);
      rObject parent = tags;
      rObject where = stacks_.self();
      tag_chain_type chain = decompose_tag_chain(e);
      rforeach (const libport::Symbol& elt, chain)
      {
	// Check whether the concerned level in the chain already
	// exists.
	if (rObject owner = where->slot_locate(elt).first)
        {
          LIBPORT_DEBUG("Component " << elt << " exists.");
	  where = owner->local_slot_get(elt)->value();
	  if (object::Tag* parent_ = dynamic_cast<object::Tag*>(where.get()))
	  {
            LIBPORT_DEBUG("It is a tag, so use it as the new parent.");
	    parent = parent_;
	  }
        }
	else
	{
	  // We have to create a new tag, which will be attached
	  // to the upper level (hierarchical tags, implicitly
	  // rooted by Tags).
	  where = parent->call(SYMBOL(new), new object::String(elt));
	  parent->slot_set(elt, where);
	  parent = where;
	}
      }

      return where;
    }
  }

  void
  Interpreter::show_backtrace(const call_stack_type& bt,
                              const std::string& chan)
  {
    rforeach (const call_type& c, bt)
    {
      std::ostringstream o;
      o << "!!!    called from: " << c;
      send_message(chan, o.str());
    }
  }

  void
  Interpreter::show_backtrace(const std::string& chan)
  {
    show_backtrace(call_stack_, chan);
  }

  Interpreter::backtrace_type
  Interpreter::backtrace_get() const
  {
    CAPTURE_GLOBAL(StackFrame);
    backtrace_type res;
    foreach (call_type c, call_stack_)
    {
      rObject loc = object::nil_class;
      if (c.second)
        loc = new object::Location(c.second.get());
      rObject frame =
        StackFrame
        ->call("new", new object::String(c.first.name_get()), loc);
      res.push_back(frame_type(frame));
    }
    return res;
  }

  object::call_stack_type
  Interpreter::call_stack_get() const
  {
    return call_stack_;
  }

  void
  Interpreter::raise(rObject exn, bool skip_last)
  {
    CAPTURE_GLOBAL(Exception);

    // innermost_node_ can be empty if the interpreter has not interpreted
    // any urbiscript.  E.g., slot_set can raise an exception only from the
    // C++ side.  It would be better to produce a C++ backtrace instead.
    if (is_a(exn, Exception) && innermost_node_)
    {
      boost::optional<ast::loc> l;
      if (object::is_system_location(innermost_node_->location_get()))
      {
        rforeach(const call_type& c, call_stack_get())
          if (c.second)
          {
            l = c.second;
            break;
          }
      }
      else
        l = innermost_node_->location_get();
      if (l)
        exn->slot_update(SYMBOL(location),
                         new object::String(string_cast(*l)));
      exn->slot_update(SYMBOL(backtrace),
                       as_job()->as<object::Job>()->backtrace());
    }
    call_stack_type bt = call_stack_get();
    if (skip_last && !bt.empty())
      bt.pop_back();
    throw object::UrbiException(exn, bt);
  }

} // namespace runner

// If not in speed mode, compile visit methods here.
#ifndef LIBPORT_COMPILATION_MODE_SPEED
# include <runner/interpreter-visit.hxx>
#endif
<|endoftext|>