<commit_before>#include "cppjson.h"
#include <stdio.h>
#include <sstream>

void verify(const json::Value &value, const char *encoded)
{
	/* try to encode the value and verify that it decodes to the same */
	std::ostringstream ss;
	value.write(ss);
	json::Value value2;
	std::istringstream parser(ss.str());
	value2.load_all(parser);
	assert(value == value2);

	/* try to load the JSON string, and check that it is equal */
	parser.str(encoded);
	parser.clear();
	value2.load_all(parser);
	assert(value == value2);

	/* Verify lazy loading */
	parser.str(encoded);
	parser.clear();
	value2.load_all(parser, true);
}

void verify_error(const char *s, const char *error)
{
	json::Value val;
	std::istringstream ss(s);
	try {
		val.load_all(ss);
		/* should always raise an exception */
		assert(0);
	} catch (const json::decode_error &e) {
		assert(e.what() == std::string(error));
	}
}

void test_lazy_array()
{
	std::istringstream parser("{\"a\": [1, \"foo\"], \"b\": [2, \"bar\"]}");
	json::Value value;
	value.load_all(parser, true);
	json::Value &a = value.get("a");
	json::Value &b = value.get("b");
	assert(a.load_next().as_integer() == 1);
	assert(b.load_next().as_integer() == 2);
	assert(a.load_next().as_string() == "foo");
	bool end = false;
	a.load_next(&end);
	assert(end);
	assert(b.load_next().as_string() == "bar");
	b.load_next(&end);
	assert(end);
}

int main()
{
	const uint8_t snowman[] = {0xE2, 0x98, 0x83, 0};

	verify(1234, "1234");
	verify(-1234, "-1234");
	verify(1234, "1234.");
	verify(1234, "1234 // a comment\n\n");
	verify(1234, "//a comment\n\n1234");
	verify(1234, "//\n1234");
	verify(1234.0, "1234");
	verify(1234.56, "1234.56");
	verify(-1234.56, "-1234.56");
	verify(1234, "\t1234 \n");
	verify("foobar", "\"foobar\"");
	verify("snow" + std::string((char *) snowman) + "man", "\"snow\u2603man\"");
	verify("", "\"\"");
	verify(" /\r\n \"\\", "\" \\/\\r\\n \\\"\\\\\" ");
	verify(true, "true");
	verify(false, "false");

	std::vector<json::Value> arr;
	verify(arr, "[] ");

	arr.push_back("foo");
	arr.push_back(1234);
	arr.push_back(-1234.56);
	arr.push_back(true);
	verify(arr, "[\"foo\",\n 1234,\t-1234.56\n, true] ");

	json::object_map_t obj;
	verify(obj, "{}");
	obj["bar"] = arr;
	obj["foo"] = "test";
	verify(obj, "{\"bar\" :[ \"foo\" ,1234,-1234.56, true, ], \"foo\": \"test\"}\n");

	std::vector<json::Value> arr2;
	arr2.push_back(obj);
	arr2.push_back(123);
	verify(arr2, "[{\"bar\":[\"foo\",1234 ,-1234.56,true],\"foo\":\"test\"} ,123\n]");

	verify_error("foobar", "Unknown keyword in input");
	verify_error("-foo", "Expected a digit");
	verify_error("trueorfalse", "Unknown keyword in input");
	verify_error("\"foobar", "Unexpected end of input");
	verify_error("[,] ", "Unknown character in input");
	verify_error("[1234, ", "Unexpected end of input");
	verify_error(" [1 2]", "Expected ',' or ']'");
	verify_error("{\"foo\": ,} ", "Unknown character in input");
	verify_error("{ \"foo\": 1234, ", "Unexpected end of input");
	verify_error("{1234.56}", "Expected a string");
	verify_error("{\"a\": [] ", "Expected ',' or '}'");
	verify_error("{\"a\" 5 ", "Expected ':'");
	verify_error("11111111111111111111", "Invalid integer");
	verify_error(" /", "Expected '/'");

	test_lazy_array();

	printf("ok\n");
	return 0;
}
<commit_msg>Fix UTF-8 test case [CORRECTIVE]<commit_after>#include "cppjson.h"
#include <stdio.h>
#include <sstream>

void verify(const json::Value &value, const char *encoded)
{
	/* try to encode the value and verify that it decodes to the same */
	std::ostringstream ss;
	value.write(ss);
	json::Value value2;
	std::istringstream parser(ss.str());
	value2.load_all(parser);
	assert(value == value2);

	/* try to load the JSON string, and check that it is equal */
	parser.str(encoded);
	parser.clear();
	value2.load_all(parser);
	assert(value == value2);

	/* Verify lazy loading */
	parser.str(encoded);
	parser.clear();
	value2.load_all(parser, true);
}

void verify_error(const char *s, const char *error)
{
	json::Value val;
	std::istringstream ss(s);
	try {
		val.load_all(ss);
		/* should always raise an exception */
		assert(0);
	} catch (const json::decode_error &e) {
		assert(e.what() == std::string(error));
	}
}

void test_lazy_array()
{
	std::istringstream parser("{\"a\": [1, \"foo\"], \"b\": [2, \"bar\"]}");
	json::Value value;
	value.load_all(parser, true);
	json::Value &a = value.get("a");
	json::Value &b = value.get("b");
	assert(a.load_next().as_integer() == 1);
	assert(b.load_next().as_integer() == 2);
	assert(a.load_next().as_string() == "foo");
	bool end = false;
	a.load_next(&end);
	assert(end);
	assert(b.load_next().as_string() == "bar");
	b.load_next(&end);
	assert(end);
}

int main()
{
	const uint8_t snowman[] = {0xE2, 0x98, 0x83, 0};

	verify(1234, "1234");
	verify(-1234, "-1234");
	verify(1234, "1234.");
	verify(1234, "1234 // a comment\n\n");
	verify(1234, "//a comment\n\n1234");
	verify(1234, "//\n1234");
	verify(1234.0, "1234");
	verify(1234.56, "1234.56");
	verify(-1234.56, "-1234.56");
	verify(1234, "\t1234 \n");
	verify("foobar", "\"foobar\"");
	verify("snow" + std::string((char *) snowman) + "man", "\"snow\\u2603man\"");
	verify("", "\"\"");
	verify(" /\r\n \"\\", "\" \\/\\r\\n \\\"\\\\\" ");
	verify(true, "true");
	verify(false, "false");

	std::vector<json::Value> arr;
	verify(arr, "[] ");

	arr.push_back("foo");
	arr.push_back(1234);
	arr.push_back(-1234.56);
	arr.push_back(true);
	verify(arr, "[\"foo\",\n 1234,\t-1234.56\n, true] ");

	json::object_map_t obj;
	verify(obj, "{}");
	obj["bar"] = arr;
	obj["foo"] = "test";
	verify(obj, "{\"bar\" :[ \"foo\" ,1234,-1234.56, true, ], \"foo\": \"test\"}\n");

	std::vector<json::Value> arr2;
	arr2.push_back(obj);
	arr2.push_back(123);
	verify(arr2, "[{\"bar\":[\"foo\",1234 ,-1234.56,true],\"foo\":\"test\"} ,123\n]");

	verify_error("foobar", "Unknown keyword in input");
	verify_error("-foo", "Expected a digit");
	verify_error("trueorfalse", "Unknown keyword in input");
	verify_error("\"foobar", "Unexpected end of input");
	verify_error("[,] ", "Unknown character in input");
	verify_error("[1234, ", "Unexpected end of input");
	verify_error(" [1 2]", "Expected ',' or ']'");
	verify_error("{\"foo\": ,} ", "Unknown character in input");
	verify_error("{ \"foo\": 1234, ", "Unexpected end of input");
	verify_error("{1234.56}", "Expected a string");
	verify_error("{\"a\": [] ", "Expected ',' or '}'");
	verify_error("{\"a\" 5 ", "Expected ':'");
	verify_error("11111111111111111111", "Invalid integer");
	verify_error(" /", "Expected '/'");

	test_lazy_array();

	printf("ok\n");
	return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2019 Google LLC. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "wait.h"

#include <condition_variable>  // NOLINT(build/c++11)
#include <functional>
#include <mutex>  // NOLINT(build/c++11)

#include "time.h"

namespace ruy {

void WaitUntil(const std::function<bool()>& condition,
               const Duration& spin_duration, std::condition_variable* condvar,
               std::mutex* mutex) {
  // First, trivial case where the `condition` is already true;
  if (condition()) {
    return;
  }

  // Then try busy-waiting.
  const TimePoint wait_start = Clock::now();
  while (Clock::now() - wait_start < spin_duration) {
    if (condition()) {
      return;
    }
  }

  // Finally, do real passive waiting.
  //
  // TODO(b/135624397): We really want wait_until(TimePoint::max()) but that
  // runs into a libc++ bug at the moment, see b/135624397 and
  // https://bugs.llvm.org/show_bug.cgi?id=21395#c5. We pick a duration large
  // enough to appear infinite in practice and small enough to avoid such
  // overflow bugs...
  const Duration& timeout = DurationFromSeconds(1e6);
  std::unique_lock<std::mutex> lock(*mutex);
  condvar->wait_for(lock, timeout, condition);
}

void WaitUntil(const std::function<bool()>& condition,
               std::condition_variable* condvar, std::mutex* mutex) {
  // This value was empirically derived with some microbenchmark, we don't have
  // high confidence in it.
  //
  // TODO(b/135595069): make this value configurable at runtime.
  // I almost wanted to file another bug to ask for experimenting in a more
  // principled way to tune this value better, but this would have to be tuned
  // on real end-to-end applications and we'd expect different applications to
  // require different tunings. So the more important point is the need for
  // this to be controllable by the application.
  //
  // That this value means that we may be sleeping substantially longer
  // than a scheduler timeslice's duration is not necessarily surprising. The
  // idea is to pick up quickly new work after having finished the previous
  // workload. When it's new work within the same GEMM as the previous work, the
  // time interval that we might be busy-waiting is very small, so for that
  // purpose it would be more than enough to sleep for 1 ms.
  // That is all what we would observe on a GEMM benchmark. However, in a real
  // application, after having finished a GEMM, we might do unrelated work for
  // a little while, then start on a new GEMM. In that case the wait interval
  // may be a little longer. There may also not be another GEMM for a long time,
  // in which case we'll end up passively waiting below.
  const double kMaxBusyWaitSeconds = 2e-3;
  const Duration spin_duration = DurationFromSeconds(kMaxBusyWaitSeconds);
  WaitUntil(condition, spin_duration, condvar, mutex);
}

}  // namespace ruy
<commit_msg>Use condition_variable::wait, it has an overload taking a predicate that was what I wanted all along.<commit_after>/* Copyright 2019 Google LLC. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "wait.h"

#include <condition_variable>  // NOLINT(build/c++11)
#include <functional>
#include <mutex>  // NOLINT(build/c++11)

#include "time.h"

namespace ruy {

void WaitUntil(const std::function<bool()>& condition,
               const Duration& spin_duration, std::condition_variable* condvar,
               std::mutex* mutex) {
  // First, trivial case where the `condition` is already true;
  if (condition()) {
    return;
  }

  // Then try busy-waiting.
  const TimePoint wait_start = Clock::now();
  while (Clock::now() - wait_start < spin_duration) {
    if (condition()) {
      return;
    }
  }

  // Finally, do real passive waiting.
  std::unique_lock<std::mutex> lock(*mutex);
  condvar->wait(lock, condition);
}

void WaitUntil(const std::function<bool()>& condition,
               std::condition_variable* condvar, std::mutex* mutex) {
  // This value was empirically derived with some microbenchmark, we don't have
  // high confidence in it.
  //
  // TODO(b/135595069): make this value configurable at runtime.
  // I almost wanted to file another bug to ask for experimenting in a more
  // principled way to tune this value better, but this would have to be tuned
  // on real end-to-end applications and we'd expect different applications to
  // require different tunings. So the more important point is the need for
  // this to be controllable by the application.
  //
  // That this value means that we may be sleeping substantially longer
  // than a scheduler timeslice's duration is not necessarily surprising. The
  // idea is to pick up quickly new work after having finished the previous
  // workload. When it's new work within the same GEMM as the previous work, the
  // time interval that we might be busy-waiting is very small, so for that
  // purpose it would be more than enough to sleep for 1 ms.
  // That is all what we would observe on a GEMM benchmark. However, in a real
  // application, after having finished a GEMM, we might do unrelated work for
  // a little while, then start on a new GEMM. In that case the wait interval
  // may be a little longer. There may also not be another GEMM for a long time,
  // in which case we'll end up passively waiting below.
  const double kMaxBusyWaitSeconds = 2e-3;
  const Duration spin_duration = DurationFromSeconds(kMaxBusyWaitSeconds);
  WaitUntil(condition, spin_duration, condvar, mutex);
}

}  // namespace ruy
<|endoftext|>


<commit_before>#include <iostream>
#include <ostream>
#include <chrono>
#include <thread>

namespace {

void out(const char* c) { std::cout << c << std::flush; }
void clear(int n) { for (int i = 0; i < n; ++i) out("\b"); }

struct Kirby final {
  Kirby() : state{hand::mid} { out(visual::mid); }

  void left() {
    clear(visual::size);
    out(visual::left);
    state = hand::left;
  }

  void mid() {
    clear(visual::size);
    out(visual::mid);
    state = hand::mid;
  }

  void right() {
    clear(visual::size);
    out(visual::right);
    state = hand::right;
  }

private:
  enum class hand { left, mid, right } state;

  struct visual {
    static const int size;
    static const char* left;
    static const char* mid;
    static const char* right;
  };
};

const int Kirby::visual::size = 7;
const char* Kirby::visual::left = "<(^-^<)";
const char* Kirby::visual::mid = "<(^-^)>";
const char* Kirby::visual::right = "(>^-^)>";

template <std::size_t N, typename Fn>
void seq(Fn fn) {
  std::this_thread::sleep_for(std::chrono::seconds{N});
  fn();
}

template <std::size_t N, typename Fn, typename... Fns>
void seq(Fn fn, Fns... rest) {
  seq<N>(fn);
  seq<N>(rest...);
}

} // ns

int main() {
  Kirby k;

  for (int i = 0; i < 2; ++i)
    seq<1>([&] { k.left(); }, [&] { k.mid(); }, [&] { k.right(); }, [&] { k.mid(); });
}
<commit_msg>Stateless<commit_after>#include <iostream>
#include <ostream>
#include <chrono>
#include <thread>

namespace {

void out(const char* c) { std::cout << c << std::flush; }
void clear(int n) { for (int i = 0; i < n; ++i) out("\b"); }

struct Kirby final {
  Kirby() { out(visual::mid); }

  void left() {
    clear(visual::size);
    out(visual::left);
  }

  void mid() {
    clear(visual::size);
    out(visual::mid);
  }

  void right() {
    clear(visual::size);
    out(visual::right);
  }

private:
  struct visual {
    static const int size;
    static const char* left;
    static const char* mid;
    static const char* right;
  };
};

const int Kirby::visual::size = 7;
const char* Kirby::visual::left = "<(^-^<)";
const char* Kirby::visual::mid = "<(^-^)>";
const char* Kirby::visual::right = "(>^-^)>";

template <std::size_t N, typename Fn>
void seq(Fn fn) {
  std::this_thread::sleep_for(std::chrono::seconds{N});
  fn();
}

template <std::size_t N, typename Fn, typename... Fns>
void seq(Fn fn, Fns... rest) {
  seq<N>(fn);
  seq<N>(rest...);
}

} // ns

int main() {
  Kirby k;

  for (int i = 0; i < 2; ++i)
    seq<1>([&] { k.left(); }, [&] { k.mid(); }, [&] { k.right(); }, [&] { k.mid(); });
}
<|endoftext|>


<commit_before>#include "Tape.h"
#include "constants.h"

Tape::Tape()
{
  this->tape.push_back(BLANK_SYMBOL);
  this->stylus = tape.begin();
}

Tape::Tape(int* symbols, int size, int position)
{
  for (int i = 0; i < size; i++)
  {
    this->tape.push_back(symbols[i]);
    if (i == position) this->stylus = tape.end();
  }
}

int Tape::getValue()
{
  return *(this->stylus);
}

void Tape::setValue(int symbol)
{
  *(this->stylus) = symbol;
}

void Tape::moveStylusRight()
{
  if (this->stylus == this->tape.end())
    this->tape.push_back(BLANK_SYMBOL);
  (this->stylus)++;
}

void Tape::moveStylusLeft()
{
  if (this->stylus == this->tape.begin())
    this->tape.push_front(BLANK_SYMBOL);
  (this->stylus)--;
}

int * Tape::getTape(int x, int y)
{}

<commit_msg>Fix iterator dereferencing bug<commit_after>#include "Tape.h"
#include "constants.h"

Tape::Tape()
{
  this->tape.push_back(BLANK_SYMBOL);
  this->stylus = tape.begin();
}

Tape::Tape(int* symbols, int size, int position)
{
  for (int i = 0; i < size; i++)
  {
    this->tape.push_back(symbols[i]);
    if (i == position)
    {
      this->stylus = tape.end();
      (this->stylus)--;  // end() returns the "past the end" object in the list
    }
  }
}

int Tape::getValue()
{
  return *(this->stylus);
}

void Tape::setValue(int symbol)
{
  *(this->stylus) = symbol;
}

void Tape::moveStylusRight()
{
  if (this->stylus == this->tape.end())
    this->tape.push_back(BLANK_SYMBOL);
  (this->stylus)++;
}

void Tape::moveStylusLeft()
{
  if (this->stylus == this->tape.begin())
    this->tape.push_front(BLANK_SYMBOL);
  (this->stylus)--;
}

int * Tape::getTape(int x, int y)
{}

<|endoftext|>


<commit_before>/*
	proxyImage.hpp
	Arsh Chauhan
	05/02/2016

	CS372 Assignment 4
	Header for Proxyimage class.
	Create a proxy image.
	Does not perform any hypothtical disk access
	unless display is called. Saves unnecessary disk
	operations.
*/

#ifndef PROXYIMAGE_HPP
#define PROXYIMAGE_HPP

#include "realImage.hpp"

class Proxyimage:public Image
{
	string fileName_;
	Realimage realImage_;

public:
	Proxyimage(string fileName);
	void display() override;

};

#endif<commit_msg>Comment readability improved:<commit_after>/*
	proxyImage.hpp
	Arsh Chauhan
	05/02/2016

	CS372 Assignment 4
	Header for Proxyimage class.
	Create a proxy image.
	Does not perform any hypothtical disk access
	unless display is called.
	Saves unnecessary disk operations.
*/

#ifndef PROXYIMAGE_HPP
#define PROXYIMAGE_HPP

#include "realImage.hpp"

class Proxyimage:public Image
{
	string fileName_;
	Realimage realImage_;

public:
	Proxyimage(string fileName);
	void display() override;

};

#endif<|endoftext|>


<commit_before>
#include "generated/services.h"

#include <QUrl>

/**
 * @brief Constructs UserStore object.
 * @param host
 *   www.evernote.com or sandbox.evernote.com
 * @param authenticationToken
 *   This token that will be used as the default token.
 */
qevercloud::UserStore::UserStore(QString host, QString authenticationToken, QObject *parent): QObject(parent)
{
    QUrl url;
    url.setScheme("https");
    url.setHost(host);
    url.setPath("/edam/user");
    url_ = url.toString(QUrl::StripTrailingSlash);
    setAuthenticationToken(authenticationToken);
}

/**
 * Constructs NoteStore object.
 * @param noteStoreUrl
 * EDAM NoteStore service url. In general it's different for different users.
 * @param authenticationToken
 *  This token that will be used as the default token.
 *
 */
qevercloud::NoteStore::NoteStore(QString noteStoreUrl, QString authenticationToken, QObject *parent): QObject(parent)
{
    setNoteStoreUrl(noteStoreUrl);
    setAuthenticationToken(authenticationToken);
}

/**
 * Constructs NoteStore object.
 *
 * noteStoreUrl and possibly authenticationToken are expected to be specified later.
 */
qevercloud::NoteStore::NoteStore(QObject *parent): QObject(parent)
{

}

/** @fn qevercloud::UserStore:setAuthenticationToken
 * Sets a value that will be used as the default token.
 * */

/** @fn qevercloud::UserStore:authenticationToken
 * @returns the default authentication token value.
 * */

/** @fn qevercloud::NoteStore:setAuthenticationToken
 * Sets a value that will be used as the default token.
 * */

/** @fn qevercloud::NoteStore:authenticationToken
 * @returns the default authentication token value.
 * */

/** @fn qevercloud::NoteStore:setNoteStoreUrl
 * Sets a value that will be used as EDAM NoteStore service url by this object.
 * */

/** @fn qevercloud::NoteStore:authenticationToken
 * @returns EDAM NoteStore service url that is used by this NoteStore object.
 * */
<commit_msg>fix doc<commit_after>
#include "generated/services.h"

#include <QUrl>

/**
 * @brief Constructs UserStore object.
 * @param host
 *   www.evernote.com or sandbox.evernote.com
 * @param authenticationToken
 *   This token that will be used as the default token.
 */
qevercloud::UserStore::UserStore(QString host, QString authenticationToken, QObject *parent): QObject(parent)
{
    QUrl url;
    url.setScheme("https");
    url.setHost(host);
    url.setPath("/edam/user");
    url_ = url.toString(QUrl::StripTrailingSlash);
    setAuthenticationToken(authenticationToken);
}

/**
 * Constructs NoteStore object.
 * @param noteStoreUrl
 * EDAM NoteStore service url. In general it's different for different users.
 * @param authenticationToken
 *  This token that will be used as the default token.
 *
 */
qevercloud::NoteStore::NoteStore(QString noteStoreUrl, QString authenticationToken, QObject *parent): QObject(parent)
{
    setNoteStoreUrl(noteStoreUrl);
    setAuthenticationToken(authenticationToken);
}

/**
 * Constructs NoteStore object.
 *
 * noteStoreUrl and possibly authenticationToken are expected to be specified later.
 */
qevercloud::NoteStore::NoteStore(QObject *parent): QObject(parent)
{

}

/** @fn qevercloud::UserStore::setAuthenticationToken
 * Sets a value that will be used as the default token.
 * */

/** @fn qevercloud::UserStore::authenticationToken
 * @returns the default authentication token value.
 * */

/** @fn qevercloud::NoteStore::setAuthenticationToken
 * Sets a value that will be used as the default token.
 * */

/** @fn qevercloud::NoteStore::authenticationToken
 * @returns the default authentication token value.
 * */

/** @fn qevercloud::NoteStore::setNoteStoreUrl
 * Sets a value that will be used as EDAM NoteStore service url by this object.
 * */

/** @fn qevercloud::NoteStore::authenticationToken
 * @returns EDAM NoteStore service url that is used by this NoteStore object.
 * */
<|endoftext|>


<commit_before>#include "prochelper.hpp"
#include "glx.hpp"
#include "input.hpp"
#include "sound.hpp"

namespace rs {
	// ------------------------------ DrawProc ------------------------------
	bool DrawProc::runU(uint64_t accum, bool bSkip) {
		auto lk = sharedbase.lock();
		auto& fx = *lk->hlFx.ref();
		if(!bSkip) {
			lk->fps.update();
			fx.execTask();
		}
		return !bSkip;
	}
	// ------------------------------ MainProc ------------------------------
	MainProc::MainProc(const rs::SPWindow& sp, bool bInitInput):
		_bFirstScene(false)
	{
		auto lk = sharedbase.lock();
		lk->spWindow = sp;
		lk->screenSize *= 0;
		if(bInitInput)
			_initInput();
	}
	void MainProc::_pushFirstScene(rs::HObj hObj) {
		Assert(Trap, !_bFirstScene, "pushed first scene twice")
		mgr_scene.setPushScene(hObj);
		_bFirstScene = true;
	}
	void MainProc::_initInput() {
		// キーバインディング
		auto lk = sharedbase.lock();
		lk->hlIk = rs::Keyboard::OpenKeyboard();
		lk->hlIm = rs::Mouse::OpenMouse(0);
		auto& mouse = *lk->hlIm.ref();
		mouse.setMouseMode(rs::MouseMode::Absolute);
		mouse.setDeadZone(0, 1.f, 0.f);
		mouse.setDeadZone(1, 1.f, 0.f);
	}

	bool MainProc::runU(Query& q) {
		if(!MainProc::_beginProc())
			return false;

		bool b = userRunU();
		if(b && q.canDraw()) {
			mgr_scene.onDraw();
			q.setDraw(true);
		}
		_endProc();
		return b;
	}
	bool MainProc::_beginProc() {
		Assert(Trap, _bFirstScene, "not pushed first scene yet")

		mgr_sound.update();
		// 描画コマンド
		auto lk = sharedbase.lock();
		rs::GLEffect& fx = *lk->hlFx.ref();
		// 描画スレッドの処理が遅過ぎたらここでウェイトがかかる
		fx.beginTask();
		if(mgr_scene.onUpdate()) {
			_endProc();
			return false;
		}

		// 画面のサイズとアスペクト比合わせ
		auto& scs = lk->screenSize;
		auto sz = lk->spWindow->getSize();
		if(scs != sz) {
			scs = sz;
			GL.glViewport(0,0, sz.width, sz.height);
		}
		return true;
	}
	void MainProc::_endProc() {
		auto& fx = sharedbase.lock()->hlFx.ref();
		fx->endTask();
	}
	void MainProc::onPause() {
		mgr_scene.onPause(); }
	void MainProc::onResume() {
		mgr_scene.onResume(); }
	void MainProc::onStop() {
		auto lk = sharedbase.lock();
		lk->hlFx.ref()->clearTask();
		mgr_scene.onStop();
	}
	void MainProc::onReStart() {
		mgr_scene.onReStart(); }
}

<commit_msg>sharedbaseのロックタイミングによるデッドロックを解消<commit_after>#include "prochelper.hpp"
#include "glx.hpp"
#include "input.hpp"
#include "sound.hpp"

namespace rs {
	// ------------------------------ DrawProc ------------------------------
	bool DrawProc::runU(uint64_t accum, bool bSkip) {
		auto lk = sharedbase.lock();
		auto& fx = *lk->hlFx.ref();
		if(!bSkip) {
			lk->fps.update();
			fx.execTask();
		}
		return !bSkip;
	}
	// ------------------------------ MainProc ------------------------------
	MainProc::MainProc(const rs::SPWindow& sp, bool bInitInput):
		_bFirstScene(false)
	{
		auto lk = sharedbase.lock();
		lk->spWindow = sp;
		lk->screenSize *= 0;
		if(bInitInput)
			_initInput();
	}
	void MainProc::_pushFirstScene(rs::HObj hObj) {
		Assert(Trap, !_bFirstScene, "pushed first scene twice")
		mgr_scene.setPushScene(hObj);
		_bFirstScene = true;
	}
	void MainProc::_initInput() {
		// キーバインディング
		auto lk = sharedbase.lock();
		lk->hlIk = rs::Keyboard::OpenKeyboard();
		lk->hlIm = rs::Mouse::OpenMouse(0);
		auto& mouse = *lk->hlIm.ref();
		mouse.setMouseMode(rs::MouseMode::Absolute);
		mouse.setDeadZone(0, 1.f, 0.f);
		mouse.setDeadZone(1, 1.f, 0.f);
	}

	bool MainProc::runU(Query& q) {
		if(!MainProc::_beginProc())
			return false;

		bool b = userRunU();
		if(b && q.canDraw()) {
			mgr_scene.onDraw();
			q.setDraw(true);
		}
		_endProc();
		return b;
	}
	bool MainProc::_beginProc() {
		Assert(Trap, _bFirstScene, "not pushed first scene yet")

		mgr_sound.update();
		// 描画コマンド
		rs::GLEffect* fx;
		{
			auto lk = sharedbase.lock();
			fx = lk->hlFx->get();
		}
		// 描画スレッドの処理が遅過ぎたらここでウェイトがかかる
		fx->beginTask();
		if(mgr_scene.onUpdate()) {
			_endProc();
			return false;
		}

		// 画面のサイズとアスペクト比合わせ
		{
			auto lk = sharedbase.lock();
			auto& scs = lk->screenSize;
			auto sz = lk->spWindow->getSize();
			if(scs != sz) {
				scs = sz;
				GL.glViewport(0,0, sz.width, sz.height);
			}
		}
		return true;
	}
	void MainProc::_endProc() {
		auto& fx = sharedbase.lock()->hlFx.ref();
		fx->endTask();
	}
	void MainProc::onPause() {
		mgr_scene.onPause(); }
	void MainProc::onResume() {
		mgr_scene.onResume(); }
	void MainProc::onStop() {
		auto lk = sharedbase.lock();
		lk->hlFx.ref()->clearTask();
		mgr_scene.onStop();
	}
	void MainProc::onReStart() {
		mgr_scene.onReStart(); }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"

/*! Inits permit join manager.

    The manager will observe and ensure the global permit join state.
 */
void DeRestPluginPrivate::initPermitJoin()
{
    permitJoinFlag = false;
    permitJoinTimer = new QTimer(this);
    permitJoinTimer->setSingleShot(false);
    connect(permitJoinTimer, SIGNAL(timeout()),
            this, SLOT(permitJoinTimerFired()));
    permitJoinTimer->start(1000);
    permitJoinLastSendTime = QTime::currentTime();

    resendPermitJoinTimer = new QTimer(this);
    resendPermitJoinTimer->setSingleShot(true);
    connect(resendPermitJoinTimer, SIGNAL(timeout()),
            this, SLOT(resendPermitJoinTimerFired()));
}

/*! Sets the permit join interval

    \param duration specifies the interval in which joining is enabled
               - 0 disabled
               - 1..254 duration in seconds until joining will be disabled
               - 255 always permit
 * \return
 */
bool DeRestPluginPrivate::setPermitJoinDuration(uint8_t duration)
{
    if (gwPermitJoinDuration != duration)
    {
        gwPermitJoinDuration = duration;
    }

    // force resend
    permitJoinLastSendTime = QTime();
    return true;
}

/*! Send Commissioning Mode command to GP proxy device.
 */
bool DeRestPluginPrivate::sendGPProxyCommissioningMode()
{
    deCONZ::ApsDataRequest req;

    req.setDstAddressMode(deCONZ::ApsNwkAddress);
    req.dstAddress().setNwk(deCONZ::BroadcastRouters);
    req.setProfileId(GP_PROFILE_ID);
    req.setClusterId(GREEN_POWER_CLUSTER_ID);
    req.setDstEndpoint(GREEN_POWER_ENDPOINT);
    req.setSrcEndpoint(GREEN_POWER_ENDPOINT);
    req.setTxOptions(nullptr);
    req.setRadius(0);

    QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian);

    deCONZ::ZclFrame zclFrame;

    zclFrame.setSequenceNumber(zclSeq++);
    zclFrame.setCommandId(0x02); // commissioning mode
    zclFrame.setFrameControl(deCONZ::ZclFCClusterCommand |
                             deCONZ::ZclFCDirectionServerToClient |
                             deCONZ::ZclFCDisableDefaultResponse);

    { // payload
        QDataStream stream(&zclFrame.payload(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        quint8 options = 0x0b; // enter commissioning mode, exit on window expire
        quint16 window = 40;
        stream << options;
        stream << window;
    }

    { // ZCL frame

        QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        zclFrame.writeToStream(stream);
    }

    // broadcast
    if (apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
    {
        DBG_Printf(DBG_INFO, "send GP proxy commissioning mode\n");
        return true;
    }

    DBG_Printf(DBG_INFO, "send GP proxy commissioning mode failed\n");
    return false;
}

/*! Send Pair command to GP proxy device.
 */
bool DeRestPluginPrivate::sendGPPairing(quint32 gpdSrcId, quint16 sinkGroupId, quint8 deviceId, quint32 frameCounter, const quint8 *key)
{
    deCONZ::ApsDataRequest req;

    req.setDstAddressMode(deCONZ::ApsNwkAddress);
    req.dstAddress().setNwk(deCONZ::BroadcastRouters);
    req.setProfileId(GP_PROFILE_ID);
    req.setClusterId(GREEN_POWER_CLUSTER_ID);
    req.setDstEndpoint(GREEN_POWER_ENDPOINT);
    req.setSrcEndpoint(GREEN_POWER_ENDPOINT);
    req.setTxOptions(nullptr);
    req.setRadius(0);

    QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian);

    deCONZ::ZclFrame zclFrame;

    zclFrame.setSequenceNumber(zclSeq++);
    zclFrame.setCommandId(0x01); // pairing
    zclFrame.setFrameControl(deCONZ::ZclFCClusterCommand |
                             deCONZ::ZclFCDirectionServerToClient |
                             deCONZ::ZclFCDisableDefaultResponse);

    { // payload
        QDataStream stream(&zclFrame.payload(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        frameCounter = 0;

        quint8 options0 = 0x48; // enter commissioning mode, exit on window expire
        //quint8 options1 = key ? 0xe5 : 0x65;
        quint8 options1 = 0x40;
        quint8 options2 = 0x00;
        stream << options0;
        stream << options1;
        stream << options2;
        stream << gpdSrcId;
        stream << sinkGroupId;
        stream << deviceId;
        stream << frameCounter;

        if (key)
        {
//          for (size_t  i = 0; i < 16; i++)
//          {
//              stream << (quint8)key[i];
//          }
        }
    }

    { // ZCL frame

        QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        zclFrame.writeToStream(stream);
    }

    // broadcast
    if (apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
    {
        DBG_Printf(DBG_INFO, "send GP pairing\n");
        return true;
    }

    DBG_Printf(DBG_INFO, "send GP pairing\n");
    return false;
}

/*! Handle broadcasting of permit join interval.

    This is done every PERMIT_JOIN_SEND_INTERVAL to ensure
    any node in the network has the same settings.
 */
void DeRestPluginPrivate::permitJoinTimerFired()
{
    Q_Q(DeRestPlugin);
    if (!q->pluginActive() || !apsCtrl)
    {
        return;
    }

    if ((gwPermitJoinDuration > 0) && (gwPermitJoinDuration < 255))
    {
        permitJoinFlag = true;
        gwPermitJoinDuration--;

        if ((gwPermitJoinDuration % 10) == 0)
        {
            // try to add light nodes even if they existed in deCONZ bevor and therefore
            // no node added event will be triggert in this phase
            int i = 0;
            const deCONZ::Node *node = nullptr;
            while (apsCtrl->getNode(i, &node) == 0)
            {
                if (node && !node->isZombie() &&
                        !node->nodeDescriptor().isNull() && node->nodeDescriptor().receiverOnWhenIdle())
                {
                    addLightNode(node);
                }
                i++;
            }
        }
        else if ((gwPermitJoinDuration % 15) == 0)
        {
            for (LightNode &l : nodes)
            {
                if (l.isAvailable() && l.modelId().isEmpty())
                {
                    queuePollNode(&l);
                }
            }
        }

        updateEtag(gwConfigEtag); // update Etag so that webApp can count down permitJoin duration
    }

    if (gwPermitJoinDuration == 0 && permitJoinFlag)
    {
        permitJoinFlag = false;
    }

    if (!isInNetwork())
    {
        return;
    }

//    if (gwPermitJoinDuration == 0 && otauLastBusyTimeDelta() < (60 * 5))
//    {
//        // don't pollute channel while OTA is running
//        return;
//    }

    QTime now = QTime::currentTime();
    int diff = permitJoinLastSendTime.msecsTo(now);

    if (!permitJoinLastSendTime.isValid() || (diff > PERMIT_JOIN_SEND_INTERVAL))
    {
        deCONZ::ApsDataRequest apsReq;
        quint8 tcSignificance = 0x01;

        apsReq.setDstAddressMode(deCONZ::ApsNwkAddress);
        apsReq.dstAddress().setNwk(deCONZ::BroadcastRouters);
        apsReq.setProfileId(ZDP_PROFILE_ID);
        apsReq.setClusterId(ZDP_MGMT_PERMIT_JOINING_REQ_CLID);
        apsReq.setDstEndpoint(ZDO_ENDPOINT);
        apsReq.setSrcEndpoint(ZDO_ENDPOINT);
        apsReq.setTxOptions(0);
        apsReq.setRadius(0);

        QDataStream stream(&apsReq.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        stream << (uint8_t)now.second(); // seqno
        stream << gwPermitJoinDuration;
        stream << tcSignificance;

        DBG_Assert(apsCtrl != 0);

        if (!apsCtrl)
        {
            return;
        }

        // set for own node
        apsCtrl->setPermitJoin(gwPermitJoinDuration);

        // broadcast
        if (apsCtrl->apsdeDataRequest(apsReq) == deCONZ::Success)
        {
            DBG_Printf(DBG_INFO, "send permit join, duration: %d\n", gwPermitJoinDuration);
            permitJoinLastSendTime = now;

            if (gwPermitJoinDuration > 0)
            {
                // sendGPProxyCommissioningMode(); TODO enable when GP security is implemented
            }
        }
        else
        {
            DBG_Printf(DBG_INFO, "send permit join failed\n");
        }
    }
}

/*! Check if permitJoin is > 60 seconds then resend permitjoin with 60 seconds
 */
void DeRestPluginPrivate::resendPermitJoinTimerFired()
{
    resendPermitJoinTimer->stop();
    if (gwPermitJoinDuration <= 1)
    {
        if (gwPermitJoinResend > 0)
        {
            if (gwPermitJoinResend >= 60)
            {
                setPermitJoinDuration(60);
            }
            else
            {
                setPermitJoinDuration(gwPermitJoinResend);
            }
            gwPermitJoinResend -= 60;
            updateEtag(gwConfigEtag);
            if (gwPermitJoinResend <= 0)
            {
                gwPermitJoinResend = 0;
                return;
            }

        }
        else if (gwPermitJoinResend == 0)
        {
            setPermitJoinDuration(0);
            return;
        }
    }
    else if (gwPermitJoinResend == 0)
    {
        setPermitJoinDuration(0);
        return;
    }
    resendPermitJoinTimer->start(1000);
}
<commit_msg>Fix permit join not reset to 0<commit_after>/*
 * Copyright (c) 2016-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"

/*! Inits permit join manager.

    The manager will observe and ensure the global permit join state.
 */
void DeRestPluginPrivate::initPermitJoin()
{
    permitJoinFlag = false;
    permitJoinTimer = new QTimer(this);
    permitJoinTimer->setSingleShot(false);
    connect(permitJoinTimer, SIGNAL(timeout()),
            this, SLOT(permitJoinTimerFired()));
    permitJoinTimer->start(1000);
    permitJoinLastSendTime = QTime::currentTime();

    resendPermitJoinTimer = new QTimer(this);
    resendPermitJoinTimer->setSingleShot(true);
    connect(resendPermitJoinTimer, SIGNAL(timeout()),
            this, SLOT(resendPermitJoinTimerFired()));
}

/*! Sets the permit join interval

    \param duration specifies the interval in which joining is enabled
               - 0 disabled
               - 1..254 duration in seconds until joining will be disabled
               - 255 always permit
 * \return
 */
bool DeRestPluginPrivate::setPermitJoinDuration(uint8_t duration)
{
    if (gwPermitJoinDuration != duration)
    {
        gwPermitJoinDuration = duration;
    }

    // force resend
    permitJoinLastSendTime = QTime();
    return true;
}

/*! Send Commissioning Mode command to GP proxy device.
 */
bool DeRestPluginPrivate::sendGPProxyCommissioningMode()
{
    deCONZ::ApsDataRequest req;

    req.setDstAddressMode(deCONZ::ApsNwkAddress);
    req.dstAddress().setNwk(deCONZ::BroadcastRouters);
    req.setProfileId(GP_PROFILE_ID);
    req.setClusterId(GREEN_POWER_CLUSTER_ID);
    req.setDstEndpoint(GREEN_POWER_ENDPOINT);
    req.setSrcEndpoint(GREEN_POWER_ENDPOINT);
    req.setTxOptions(nullptr);
    req.setRadius(0);

    QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian);

    deCONZ::ZclFrame zclFrame;

    zclFrame.setSequenceNumber(zclSeq++);
    zclFrame.setCommandId(0x02); // commissioning mode
    zclFrame.setFrameControl(deCONZ::ZclFCClusterCommand |
                             deCONZ::ZclFCDirectionServerToClient |
                             deCONZ::ZclFCDisableDefaultResponse);

    { // payload
        QDataStream stream(&zclFrame.payload(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        quint8 options = 0x0b; // enter commissioning mode, exit on window expire
        quint16 window = 40;
        stream << options;
        stream << window;
    }

    { // ZCL frame

        QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        zclFrame.writeToStream(stream);
    }

    // broadcast
    if (apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
    {
        DBG_Printf(DBG_INFO, "send GP proxy commissioning mode\n");
        return true;
    }

    DBG_Printf(DBG_INFO, "send GP proxy commissioning mode failed\n");
    return false;
}

/*! Send Pair command to GP proxy device.
 */
bool DeRestPluginPrivate::sendGPPairing(quint32 gpdSrcId, quint16 sinkGroupId, quint8 deviceId, quint32 frameCounter, const quint8 *key)
{
    deCONZ::ApsDataRequest req;

    req.setDstAddressMode(deCONZ::ApsNwkAddress);
    req.dstAddress().setNwk(deCONZ::BroadcastRouters);
    req.setProfileId(GP_PROFILE_ID);
    req.setClusterId(GREEN_POWER_CLUSTER_ID);
    req.setDstEndpoint(GREEN_POWER_ENDPOINT);
    req.setSrcEndpoint(GREEN_POWER_ENDPOINT);
    req.setTxOptions(nullptr);
    req.setRadius(0);

    QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian);

    deCONZ::ZclFrame zclFrame;

    zclFrame.setSequenceNumber(zclSeq++);
    zclFrame.setCommandId(0x01); // pairing
    zclFrame.setFrameControl(deCONZ::ZclFCClusterCommand |
                             deCONZ::ZclFCDirectionServerToClient |
                             deCONZ::ZclFCDisableDefaultResponse);

    { // payload
        QDataStream stream(&zclFrame.payload(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        frameCounter = 0;

        quint8 options0 = 0x48; // enter commissioning mode, exit on window expire
        //quint8 options1 = key ? 0xe5 : 0x65;
        quint8 options1 = 0x40;
        quint8 options2 = 0x00;
        stream << options0;
        stream << options1;
        stream << options2;
        stream << gpdSrcId;
        stream << sinkGroupId;
        stream << deviceId;
        stream << frameCounter;

        if (key)
        {
//          for (size_t  i = 0; i < 16; i++)
//          {
//              stream << (quint8)key[i];
//          }
        }
    }

    { // ZCL frame

        QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        zclFrame.writeToStream(stream);
    }

    // broadcast
    if (apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
    {
        DBG_Printf(DBG_INFO, "send GP pairing\n");
        return true;
    }

    DBG_Printf(DBG_INFO, "send GP pairing\n");
    return false;
}

/*! Handle broadcasting of permit join interval.

    This is done every PERMIT_JOIN_SEND_INTERVAL to ensure
    any node in the network has the same settings.
 */
void DeRestPluginPrivate::permitJoinTimerFired()
{
    Q_Q(DeRestPlugin);
    if (!q->pluginActive() || !apsCtrl)
    {
        return;
    }

    if ((gwPermitJoinDuration > 0) && (gwPermitJoinDuration < 255))
    {
        permitJoinFlag = true;
        gwPermitJoinDuration--;

        if ((gwPermitJoinDuration % 10) == 0)
        {
            // try to add light nodes even if they existed in deCONZ bevor and therefore
            // no node added event will be triggert in this phase
            int i = 0;
            const deCONZ::Node *node = nullptr;
            while (apsCtrl->getNode(i, &node) == 0)
            {
                if (node && !node->isZombie() &&
                        !node->nodeDescriptor().isNull() && node->nodeDescriptor().receiverOnWhenIdle())
                {
                    addLightNode(node);
                }
                i++;
            }
        }
        else if ((gwPermitJoinDuration % 15) == 0)
        {
            for (LightNode &l : nodes)
            {
                if (l.isAvailable() && l.modelId().isEmpty())
                {
                    queuePollNode(&l);
                }
            }
        }

        updateEtag(gwConfigEtag); // update Etag so that webApp can count down permitJoin duration
    }

    if (gwPermitJoinDuration == 0 && permitJoinFlag)
    {
        permitJoinFlag = false;
    }

    if (!isInNetwork())
    {
        return;
    }

    auto ctrlPermitJoin = apsCtrl->getParameter(deCONZ::ParamPermitJoin);
    if (ctrlPermitJoin > 0 && gwPermitJoinDuration == 0)
    {
        // workaround since the firmware reports cached value instead hot value
        apsCtrl->setPermitJoin(gwPermitJoinDuration);
        permitJoinLastSendTime = {}; // force broadcast
    }

//    if (gwPermitJoinDuration == 0 && otauLastBusyTimeDelta() < (60 * 5))
//    {
//        // don't pollute channel while OTA is running
//        return;
//    }

    QTime now = QTime::currentTime();
    int diff = permitJoinLastSendTime.msecsTo(now);

    if (!permitJoinLastSendTime.isValid() || (diff > PERMIT_JOIN_SEND_INTERVAL))
    {
        deCONZ::ApsDataRequest apsReq;
        quint8 tcSignificance = 0x01;

        apsReq.setDstAddressMode(deCONZ::ApsNwkAddress);
        apsReq.dstAddress().setNwk(deCONZ::BroadcastRouters);
        apsReq.setProfileId(ZDP_PROFILE_ID);
        apsReq.setClusterId(ZDP_MGMT_PERMIT_JOINING_REQ_CLID);
        apsReq.setDstEndpoint(ZDO_ENDPOINT);
        apsReq.setSrcEndpoint(ZDO_ENDPOINT);
        apsReq.setTxOptions(0);
        apsReq.setRadius(0);

        QDataStream stream(&apsReq.asdu(), QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);

        stream << (uint8_t)now.second(); // seqno
        stream << gwPermitJoinDuration;
        stream << tcSignificance;

        DBG_Assert(apsCtrl != 0);

        if (!apsCtrl)
        {
            return;
        }

        // set for own node
        apsCtrl->setPermitJoin(gwPermitJoinDuration);

        // broadcast
        if (apsCtrl->apsdeDataRequest(apsReq) == deCONZ::Success)
        {
            DBG_Printf(DBG_INFO, "send permit join, duration: %d\n", gwPermitJoinDuration);
            permitJoinLastSendTime = now;

            if (gwPermitJoinDuration > 0)
            {
                // sendGPProxyCommissioningMode(); TODO enable when GP security is implemented
            }
        }
        else
        {
            DBG_Printf(DBG_INFO, "send permit join failed\n");
        }
    }
}

/*! Check if permitJoin is > 60 seconds then resend permitjoin with 60 seconds
 */
void DeRestPluginPrivate::resendPermitJoinTimerFired()
{
    resendPermitJoinTimer->stop();
    if (gwPermitJoinDuration <= 1)
    {
        if (gwPermitJoinResend > 0)
        {
            if (gwPermitJoinResend >= 60)
            {
                setPermitJoinDuration(60);
            }
            else
            {
                setPermitJoinDuration(gwPermitJoinResend);
            }
            gwPermitJoinResend -= 60;
            updateEtag(gwConfigEtag);
            if (gwPermitJoinResend <= 0)
            {
                gwPermitJoinResend = 0;
                return;
            }

        }
        else if (gwPermitJoinResend == 0)
        {
            setPermitJoinDuration(0);
            return;
        }
    }
    else if (gwPermitJoinResend == 0)
    {
        setPermitJoinDuration(0);
        return;
    }
    resendPermitJoinTimer->start(1000);
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/video_engine/vie_base_impl.h"

#include <string>
#include <utility>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViEBase released too many times.";
    return -1;
  }
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {}

ViEBaseImpl::~ViEBaseImpl() {}

int ViEBaseImpl::Init() {
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  LOG_F(LS_INFO) << "SetVoiceEngine";
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
                                            CpuOveruseObserver* observer) {
  LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    assert(capturer);
    capturer->RegisterCpuOveruseObserver(observer);
  }

  shared_data_.overuse_observers()->insert(
      std::pair<int, CpuOveruseObserver*>(video_channel, observer));
  return 0;
}

int ViEBaseImpl::SetCpuOveruseOptions(int video_channel,
                                      const CpuOveruseOptions& options) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->SetCpuOveruseOptions(options);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel,
                                      CpuOveruseMetrics* metrics) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->GetCpuOveruseMetrics(metrics);
      return 0;
    }
  }
  return -1;
}

void ViEBaseImpl::RegisterSendSideDelayObserver(
    int channel, SendSideDelayObserver* observer) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  assert(vie_channel);
  vie_channel->RegisterSendSideDelayObserver(observer);
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  return CreateChannel(video_channel, static_cast<const Config*>(NULL));
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               const Config* config) {
  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    config) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG(LS_INFO) << "Video channel created: " << video_channel;
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true, false);
}

int ViEBaseImpl::CreateChannelWithoutDefaultEncoder(
    int& video_channel,  // NOLINT
    int original_channel) {
  return CreateChannel(video_channel, original_channel, true, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false, true);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  LOG(LS_INFO) << "Channel deleted " << video_channel;
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
                 << ", audio channel " << audio_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  LOG_F(LS_INFO) << "StartSend: " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    LOG_F(LS_ERROR) <<  "Can't start send on a receive only channel.";
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  LOG_F(LS_INFO) << "StopSend " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StartReceive " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StopReceive " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  assert(version != NULL);
  strcpy(version, "VideoEngine 41");
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel,
                               bool sender,
                               bool disable_default_encoder) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(
          &video_channel, original_channel, sender, disable_default_encoder) ==
      -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
                 << ", base channel " << original_channel
                 << ", is send channel : " << sender;
  return 0;
}

void ViEBaseImpl::RegisterSendStatisticsProxy(
    int channel,
    SendStatisticsProxy* send_statistics_proxy) {
  LOG_F(LS_VERBOSE) << "RegisterSendStatisticsProxy on channel " << channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return;
  }
  ViEEncoder* vie_encoder = cs.Encoder(channel);
  assert(vie_encoder);

  vie_encoder->RegisterSendStatisticsProxy(send_statistics_proxy);
}

void ViEBaseImpl::RegisterReceiveStatisticsProxy(
    int channel,
    ReceiveStatisticsProxy* receive_statistics_proxy) {
  LOG_F(LS_VERBOSE) << "RegisterReceiveStatisticsProxy on channel " << channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return;
  }
  vie_channel->RegisterReceiveStatisticsProxy(receive_statistics_proxy);
}
}  // namespace webrtc
<commit_msg>Bump to version 42.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/video_engine/vie_base_impl.h"

#include <string>
#include <utility>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViEBase released too many times.";
    return -1;
  }
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {}

ViEBaseImpl::~ViEBaseImpl() {}

int ViEBaseImpl::Init() {
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  LOG_F(LS_INFO) << "SetVoiceEngine";
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
                                            CpuOveruseObserver* observer) {
  LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    assert(capturer);
    capturer->RegisterCpuOveruseObserver(observer);
  }

  shared_data_.overuse_observers()->insert(
      std::pair<int, CpuOveruseObserver*>(video_channel, observer));
  return 0;
}

int ViEBaseImpl::SetCpuOveruseOptions(int video_channel,
                                      const CpuOveruseOptions& options) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->SetCpuOveruseOptions(options);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel,
                                      CpuOveruseMetrics* metrics) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->GetCpuOveruseMetrics(metrics);
      return 0;
    }
  }
  return -1;
}

void ViEBaseImpl::RegisterSendSideDelayObserver(
    int channel, SendSideDelayObserver* observer) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  assert(vie_channel);
  vie_channel->RegisterSendSideDelayObserver(observer);
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  return CreateChannel(video_channel, static_cast<const Config*>(NULL));
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               const Config* config) {
  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    config) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG(LS_INFO) << "Video channel created: " << video_channel;
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true, false);
}

int ViEBaseImpl::CreateChannelWithoutDefaultEncoder(
    int& video_channel,  // NOLINT
    int original_channel) {
  return CreateChannel(video_channel, original_channel, true, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false, true);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  LOG(LS_INFO) << "Channel deleted " << video_channel;
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
                 << ", audio channel " << audio_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  LOG_F(LS_INFO) << "StartSend: " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    LOG_F(LS_ERROR) <<  "Can't start send on a receive only channel.";
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  LOG_F(LS_INFO) << "StopSend " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StartReceive " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StopReceive " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  assert(version != NULL);
  strcpy(version, "VideoEngine 42");
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel,
                               bool sender,
                               bool disable_default_encoder) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(
          &video_channel, original_channel, sender, disable_default_encoder) ==
      -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
                 << ", base channel " << original_channel
                 << ", is send channel : " << sender;
  return 0;
}

void ViEBaseImpl::RegisterSendStatisticsProxy(
    int channel,
    SendStatisticsProxy* send_statistics_proxy) {
  LOG_F(LS_VERBOSE) << "RegisterSendStatisticsProxy on channel " << channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return;
  }
  ViEEncoder* vie_encoder = cs.Encoder(channel);
  assert(vie_encoder);

  vie_encoder->RegisterSendStatisticsProxy(send_statistics_proxy);
}

void ViEBaseImpl::RegisterReceiveStatisticsProxy(
    int channel,
    ReceiveStatisticsProxy* receive_statistics_proxy) {
  LOG_F(LS_VERBOSE) << "RegisterReceiveStatisticsProxy on channel " << channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return;
  }
  vie_channel->RegisterReceiveStatisticsProxy(receive_statistics_proxy);
}
}  // namespace webrtc
<|endoftext|>


<commit_before>/*
	Copyright (c) 2017-2018 Andrew Depke
*/
#include "LinuxHardware.h"

#include "../../Core/Platform.h"

#include <cstring>  // std::memcpy()
#include <unistd.h>
#include <cpuid.h>
#include <thread>
#include <sys/vfs.h>

namespace Red
{
	std::string LinuxSystemHardware::GetOSName()
	{
#if OS_LINUX
		return "Linux";
#elif OS_ANDROID
		return "Android";
#elif OS_BSD
		return "BSD";
#else
		return "Unknown";
#endif
	}

	uint8_t LinuxSystemHardware::GetArchitecture()
	{
#if defined(__x86_64__) || defined(__ppc64__)
		return 64;
#else
		return 32;
#endif
	}

	std::string LinuxSystemHardware::GetCPUVendor()
	{
		unsigned int Data[4] = { 0 };
		char Vendor[13] = { 0 };

		if (__get_cpuid(0, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			// CPU vendor is stored in EBX EDX ECX (ASCII)
			std::memcpy(Vendor + 0, &Data[1], 4);  // EBX
			std::memcpy(Vendor + 4, &Data[3], 4);  // ECX
			std::memcpy(Vendor + 8, &Data[2], 4);  // EDX
		}

		else
		{
			return "Error";
		}

		Vendor[12] = '\0';

		return Vendor;
	}

	std::string LinuxSystemHardware::GetCPUBrand()
	{
		unsigned int Data[4] = { 0 };
		char Brand[49] = { 0 };

		if (__get_cpuid(0x80000002, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 0, &Data[0], 4);
			std::memcpy(Brand + 4, &Data[1], 4);
			std::memcpy(Brand + 8, &Data[2], 4);
			std::memcpy(Brand + 12, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		if (__get_cpuid(0x80000003, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 16, &Data[0], 4);
			std::memcpy(Brand + 20, &Data[1], 4);
			std::memcpy(Brand + 24, &Data[2], 4);
			std::memcpy(Brand + 28, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		if (__get_cpuid(0x80000004, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 32, &Data[0], 4);
			std::memcpy(Brand + 36, &Data[1], 4);
			std::memcpy(Brand + 40, &Data[2], 4);
			std::memcpy(Brand + 44, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		Brand[48] = '\0';

		return Brand;
	}

	unsigned int LinuxSystemHardware::GetCPUCoreCount()
	{
		return std::thread::hardware_concurrency();
	}

	unsigned long int LinuxSystemHardware::GetPhysicalMemory()
	{
		return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE));
	}

	unsigned long int LinuxSystemHardware::GetDiskSpace()
	{
		char Directory[PATH_MAX];

		if (getcwd(Directory, sizeof(Directory)))
		{
			struct statfs FileSystemStats = { 0 };

			if (statfs(Directory, &FileSystemStats) == 0)
			{
				return (FileSystemStats.f_blocks * FileSystemStats.f_bsize / 1024);
			}
		}

		return 0;
	}

	unsigned long int LinuxSystemHardware::GetDiskSpaceAvailable()
	{
		char Directory[1024];

		getcwd(Directory, sizeof(Directory));

		struct statfs FileSystemStats = { 0 };

		if (statfs(Directory, &FileSystemStats) == 0)
		{
			return (FileSystemStats.f_bavail * FileSystemStats.f_bsize / 1024);
		}

		return 0;
	}
}  // namespace Red
<commit_msg>Fixed Unused Return Value Warning<commit_after>/*
	Copyright (c) 2017-2018 Andrew Depke
*/
#include "LinuxHardware.h"

#include "../../Core/Platform.h"

#include <cstring>  // std::memcpy()
#include <unistd.h>
#include <cpuid.h>
#include <thread>
#include <sys/vfs.h>

namespace Red
{
	std::string LinuxSystemHardware::GetOSName()
	{
#if OS_LINUX
		return "Linux";
#elif OS_ANDROID
		return "Android";
#elif OS_BSD
		return "BSD";
#else
		return "Unknown";
#endif
	}

	uint8_t LinuxSystemHardware::GetArchitecture()
	{
#if defined(__x86_64__) || defined(__ppc64__)
		return 64;
#else
		return 32;
#endif
	}

	std::string LinuxSystemHardware::GetCPUVendor()
	{
		unsigned int Data[4] = { 0 };
		char Vendor[13] = { 0 };

		if (__get_cpuid(0, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			// CPU vendor is stored in EBX EDX ECX (ASCII)
			std::memcpy(Vendor + 0, &Data[1], 4);  // EBX
			std::memcpy(Vendor + 4, &Data[3], 4);  // ECX
			std::memcpy(Vendor + 8, &Data[2], 4);  // EDX
		}

		else
		{
			return "Error";
		}

		Vendor[12] = '\0';

		return Vendor;
	}

	std::string LinuxSystemHardware::GetCPUBrand()
	{
		unsigned int Data[4] = { 0 };
		char Brand[49] = { 0 };

		if (__get_cpuid(0x80000002, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 0, &Data[0], 4);
			std::memcpy(Brand + 4, &Data[1], 4);
			std::memcpy(Brand + 8, &Data[2], 4);
			std::memcpy(Brand + 12, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		if (__get_cpuid(0x80000003, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 16, &Data[0], 4);
			std::memcpy(Brand + 20, &Data[1], 4);
			std::memcpy(Brand + 24, &Data[2], 4);
			std::memcpy(Brand + 28, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		if (__get_cpuid(0x80000004, &Data[0], &Data[1], &Data[2], &Data[3]) != 0)
		{
			std::memcpy(Brand + 32, &Data[0], 4);
			std::memcpy(Brand + 36, &Data[1], 4);
			std::memcpy(Brand + 40, &Data[2], 4);
			std::memcpy(Brand + 44, &Data[3], 4);
		}

		else
		{
			return "Error";
		}

		Brand[48] = '\0';

		return Brand;
	}

	unsigned int LinuxSystemHardware::GetCPUCoreCount()
	{
		return std::thread::hardware_concurrency();
	}

	unsigned long int LinuxSystemHardware::GetPhysicalMemory()
	{
		return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE));
	}

	unsigned long int LinuxSystemHardware::GetDiskSpace()
	{
		char Directory[PATH_MAX];

		if (getcwd(Directory, sizeof(Directory)))
		{
			struct statfs FileSystemStats = { 0 };

			if (statfs(Directory, &FileSystemStats) == 0)
			{
				return (FileSystemStats.f_blocks * FileSystemStats.f_bsize / 1024);
			}
		}

		return 0;
	}

	unsigned long int LinuxSystemHardware::GetDiskSpaceAvailable()
	{
		char Directory[PATH_MAX];

		if (getcwd(Directory, sizeof(Directory)))
		{
			struct statfs FileSystemStats = { 0 };

			if (statfs(Directory, &FileSystemStats) == 0)
			{
				return (FileSystemStats.f_bavail * FileSystemStats.f_bsize / 1024);
			}
		}

		return 0;
	}
}  // namespace Red
<|endoftext|>