<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <iterator>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <audioclient.h>
#include "SoundDataWave.hpp"
#include "StreamWave.hpp"
#include "core/Engine.hpp"
#include "files/FileSystem.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

namespace ouzel
{
    namespace audio
    {
        SoundDataWave::SoundDataWave()
        {
        }

        bool SoundDataWave::init(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedEngine->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return init(newData);
        }

        bool SoundDataWave::init(const std::vector<uint8_t>& newData)
        {
            uint32_t offset = 0;

            if (newData.size() < 16) // RIFF + size + WAVE
            {
                Log(Log::Level::ERR) << "Failed to load sound file, file too small";
                return false;
            }

            if (newData[offset + 0] != 'R' ||
                newData[offset + 1] != 'I' ||
                newData[offset + 2] != 'F' ||
                newData[offset + 3] != 'F')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a RIFF format";
                return false;
            }

            offset += 4;

            uint32_t length = decodeUInt32Little(newData.data() + offset);

            offset += 4;

            if (newData.size() != length + 8)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, size mismatch";
            }

            if (newData[offset + 0] != 'W' ||
                newData[offset + 1] != 'A' ||
                newData[offset + 2] != 'V' ||
                newData[offset + 3] != 'E')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a WAVE file";
                return false;
            }

            offset += 4;

            bool formatChunkFound = false;
            bool dataChunkFound = false;

            uint16_t bitsPerSample = 0;
            uint16_t formatTag = 0;
            std::vector<uint8_t> soundData;

            for (; offset < newData.size();)
            {
                if (newData.size() < offset + 8)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                uint8_t chunkHeader[4];
                chunkHeader[0] = newData[offset + 0];
                chunkHeader[1] = newData[offset + 1];
                chunkHeader[2] = newData[offset + 2];
                chunkHeader[3] = newData[offset + 3];

                offset += 4;

                uint32_t chunkSize = decodeUInt32Little(newData.data() + offset);
                offset += 4;

                if (newData.size() < offset + chunkSize)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                if (chunkHeader[0] == 'f' && chunkHeader[1] == 'm' && chunkHeader[2] == 't' && chunkHeader[3] == ' ')
                {
                    if (chunkSize < 16)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                        return false;
                    }

                    uint32_t i = offset;

                    formatTag = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    channels = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    sampleRate = decodeUInt32Little(newData.data() + i);
                    i += 4;

                    i += 4; // average bytes per second

                    i += 2; // block align

                    bitsPerSample = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    formatChunkFound = true;
                }
                else if (chunkHeader[0] == 'd' && chunkHeader[1] == 'a' && chunkHeader[2] == 't' && chunkHeader[3] == 'a')
                {
                    soundData.assign(newData.begin() + static_cast<int>(offset), newData.begin() + static_cast<int>(offset + chunkSize));

                    dataChunkFound = true;
                }

                offset += ((chunkSize + 1) & 0xFFFFFFFE);
            }

            if (!formatChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a format chunk";
                return false;
            }

            if (!dataChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a data chunk";
                return false;
            }

            if (bitsPerSample != 8 && bitsPerSample != 16 &&
                bitsPerSample != 24 && bitsPerSample != 32)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                return false;
            }

            uint32_t bytesPerSample = bitsPerSample / 8;
            uint32_t samples = static_cast<uint32_t>(soundData.size() / bytesPerSample);
            data.resize(samples);

            if (formatTag == WAVE_FORMAT_PCM)
            {
                if (bitsPerSample == 8)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = 2.0f * static_cast<float>(soundData[i]) / 255.0f - 1.0f;
                    }
                }
                else if (bitsPerSample == 16)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = static_cast<float>(static_cast<int16_t>(soundData[i * 2] |
                                                                          (soundData[i * 2 + 1] << 8))) / 32767.0f;
                    }
                }
                else if (bitsPerSample == 24)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = static_cast<float>(static_cast<int32_t>((soundData[i * 3] << 8) |
                                                                          (soundData[i * 3 + 1] << 16) |
                                                                          (soundData[i * 3 + 2] << 24))) / 2147483648.0f;
                    }
                }
                else
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                    return false;
                }
            }
            else if (formatTag == WAVE_FORMAT_IEEE_FLOAT)
            {
                if (bitsPerSample == 32)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = reinterpret_cast<float*>(soundData.data())[i];
                    }
                }
                else
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                    return false;
                }
            }
            else
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported format";
                return false;
            }

            return true;
        }

        std::shared_ptr<Stream> SoundDataWave::createStream()
        {
            return std::make_shared<StreamWave>();
        }

        bool SoundDataWave::readData(Stream* stream, uint32_t frames, std::vector<float>& result)
        {
            StreamWave* streamWave = static_cast<StreamWave*>(stream);

            uint32_t neededSize = frames * channels;
            uint32_t totalSize = 0;

            result.resize(neededSize);

            while (neededSize > 0)
            {
                if (stream->isRepeating() && (data.size() - streamWave->getOffset()) == 0) streamWave->reset();

                if (data.size() - streamWave->getOffset() < neededSize)
                {
                    std::copy(data.begin() + streamWave->getOffset(),
                              data.end(),
                              result.begin() + totalSize);
                    totalSize += static_cast<uint32_t>(data.size() - streamWave->getOffset());
                    neededSize -= static_cast<uint32_t>(data.size() - streamWave->getOffset());
                    streamWave->setOffset(static_cast<uint32_t>(data.size()));
                }
                else
                {
                    std::copy(data.begin() + streamWave->getOffset(),
                              data.begin() + streamWave->getOffset() + neededSize,
                              result.begin() + totalSize);
                    totalSize += neededSize;
                    streamWave->setOffset(streamWave->getOffset() + neededSize);
                    neededSize = 0;
                }

                if (!stream->isRepeating()) break;
            }

            if ((data.size() - streamWave->getOffset()) == 0) streamWave->reset();

            std::fill(result.begin() + totalSize, result.end(), 0.0f);

            return true;
        }
    } // namespace audio
} // namespace ouzel
<commit_msg>Don't use Windows defines<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <iterator>
#include "SoundDataWave.hpp"
#include "StreamWave.hpp"
#include "core/Engine.hpp"
#include "files/FileSystem.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

enum WaveFormat
{
    PCM = 1,
    IEEE_FLOAT = 3
};

namespace ouzel
{
    namespace audio
    {
        SoundDataWave::SoundDataWave()
        {
        }

        bool SoundDataWave::init(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedEngine->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return init(newData);
        }

        bool SoundDataWave::init(const std::vector<uint8_t>& newData)
        {
            uint32_t offset = 0;

            if (newData.size() < 16) // RIFF + size + WAVE
            {
                Log(Log::Level::ERR) << "Failed to load sound file, file too small";
                return false;
            }

            if (newData[offset + 0] != 'R' ||
                newData[offset + 1] != 'I' ||
                newData[offset + 2] != 'F' ||
                newData[offset + 3] != 'F')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a RIFF format";
                return false;
            }

            offset += 4;

            uint32_t length = decodeUInt32Little(newData.data() + offset);

            offset += 4;

            if (newData.size() != length + 8)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, size mismatch";
            }

            if (newData[offset + 0] != 'W' ||
                newData[offset + 1] != 'A' ||
                newData[offset + 2] != 'V' ||
                newData[offset + 3] != 'E')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a WAVE file";
                return false;
            }

            offset += 4;

            bool formatChunkFound = false;
            bool dataChunkFound = false;

            uint16_t bitsPerSample = 0;
            uint16_t formatTag = 0;
            std::vector<uint8_t> soundData;

            for (; offset < newData.size();)
            {
                if (newData.size() < offset + 8)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                uint8_t chunkHeader[4];
                chunkHeader[0] = newData[offset + 0];
                chunkHeader[1] = newData[offset + 1];
                chunkHeader[2] = newData[offset + 2];
                chunkHeader[3] = newData[offset + 3];

                offset += 4;

                uint32_t chunkSize = decodeUInt32Little(newData.data() + offset);
                offset += 4;

                if (newData.size() < offset + chunkSize)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                if (chunkHeader[0] == 'f' && chunkHeader[1] == 'm' && chunkHeader[2] == 't' && chunkHeader[3] == ' ')
                {
                    if (chunkSize < 16)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                        return false;
                    }

                    uint32_t i = offset;

                    formatTag = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    channels = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    sampleRate = decodeUInt32Little(newData.data() + i);
                    i += 4;

                    i += 4; // average bytes per second

                    i += 2; // block align

                    bitsPerSample = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    formatChunkFound = true;
                }
                else if (chunkHeader[0] == 'd' && chunkHeader[1] == 'a' && chunkHeader[2] == 't' && chunkHeader[3] == 'a')
                {
                    soundData.assign(newData.begin() + static_cast<int>(offset), newData.begin() + static_cast<int>(offset + chunkSize));

                    dataChunkFound = true;
                }

                offset += ((chunkSize + 1) & 0xFFFFFFFE);
            }

            if (!formatChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a format chunk";
                return false;
            }

            if (!dataChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a data chunk";
                return false;
            }

            if (bitsPerSample != 8 && bitsPerSample != 16 &&
                bitsPerSample != 24 && bitsPerSample != 32)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                return false;
            }

            uint32_t bytesPerSample = bitsPerSample / 8;
            uint32_t samples = static_cast<uint32_t>(soundData.size() / bytesPerSample);
            data.resize(samples);

            if (formatTag == PCM)
            {
                if (bitsPerSample == 8)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = 2.0f * static_cast<float>(soundData[i]) / 255.0f - 1.0f;
                    }
                }
                else if (bitsPerSample == 16)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = static_cast<float>(static_cast<int16_t>(soundData[i * 2] |
                                                                          (soundData[i * 2 + 1] << 8))) / 32767.0f;
                    }
                }
                else if (bitsPerSample == 24)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = static_cast<float>(static_cast<int32_t>((soundData[i * 3] << 8) |
                                                                          (soundData[i * 3 + 1] << 16) |
                                                                          (soundData[i * 3 + 2] << 24))) / 2147483648.0f;
                    }
                }
                else
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                    return false;
                }
            }
            else if (formatTag == IEEE_FLOAT)
            {
                if (bitsPerSample == 32)
                {
                    for (uint32_t i = 0; i < samples; ++i)
                    {
                        data[i] = reinterpret_cast<float*>(soundData.data())[i];
                    }
                }
                else
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                    return false;
                }
            }
            else
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported format";
                return false;
            }

            return true;
        }

        std::shared_ptr<Stream> SoundDataWave::createStream()
        {
            return std::make_shared<StreamWave>();
        }

        bool SoundDataWave::readData(Stream* stream, uint32_t frames, std::vector<float>& result)
        {
            StreamWave* streamWave = static_cast<StreamWave*>(stream);

            uint32_t neededSize = frames * channels;
            uint32_t totalSize = 0;

            result.resize(neededSize);

            while (neededSize > 0)
            {
                if (stream->isRepeating() && (data.size() - streamWave->getOffset()) == 0) streamWave->reset();

                if (data.size() - streamWave->getOffset() < neededSize)
                {
                    std::copy(data.begin() + streamWave->getOffset(),
                              data.end(),
                              result.begin() + totalSize);
                    totalSize += static_cast<uint32_t>(data.size() - streamWave->getOffset());
                    neededSize -= static_cast<uint32_t>(data.size() - streamWave->getOffset());
                    streamWave->setOffset(static_cast<uint32_t>(data.size()));
                }
                else
                {
                    std::copy(data.begin() + streamWave->getOffset(),
                              data.begin() + streamWave->getOffset() + neededSize,
                              result.begin() + totalSize);
                    totalSize += neededSize;
                    streamWave->setOffset(streamWave->getOffset() + neededSize);
                    neededSize = 0;
                }

                if (!stream->isRepeating()) break;
            }

            if ((data.size() - streamWave->getOffset()) == 0) streamWave->reset();

            std::fill(result.begin() + totalSize, result.end(), 0.0f);

            return true;
        }
    } // namespace audio
} // namespace ouzel
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file listener_main.cpp
 *
 * Tool for listening to topics.
 */

#include <px4_module.h>
#include <px4_getopt.h>

#include <poll.h>

#include "topic_listener.hpp"
#include "topic_listener_generated.hpp"

extern "C" __EXPORT int listener_main(int argc, char *argv[]);

static void usage();

void listener(listener_print_topic_cb cb, const orb_id_t &id, unsigned num_msgs, int topic_instance,
	      unsigned topic_interval)
{

	if (topic_instance == -1 && num_msgs == 1) {
		// first count the number of instances
		int instances = 0;

		for (int i = 0; i < ORB_MULTI_MAX_INSTANCES; i++) {
			if (orb_exists(id, i) == PX4_OK) {
				instances++;
			}
		}

		if (instances == 1) {
			PX4_INFO_RAW("\nTOPIC: %s\n", id->o_name);
			int sub = orb_subscribe(id);
			cb(id, sub);
			orb_unsubscribe(sub);

		} else if (instances > 1) {
			PX4_INFO_RAW("\nTOPIC: %s %d instances\n", id->o_name, instances);

			for (int i = 0; i < ORB_MULTI_MAX_INSTANCES; i++) {
				if (orb_exists(id, i) == PX4_OK) {
					PX4_INFO_RAW("\nInstance %d:\n", i);
					int sub = orb_subscribe_multi(id, i);
					cb(id, sub);
					orb_unsubscribe(sub);
				}
			}
		}

	} else {
		if (orb_exists(id, topic_instance) != 0) {
			PX4_INFO_RAW("never published\n");
			return;
		}

		int sub = orb_subscribe_multi(id, topic_instance);
		orb_set_interval(sub, topic_interval);

		bool updated = false;
		unsigned i = 0;
		hrt_abstime start_time = hrt_absolute_time();

		while (i < num_msgs) {

			// check for user input to quit
			int user_input_timeout = 1;

			orb_check(sub, &updated);

			if (i == 0) {
				updated = true;
				user_input_timeout = 0;	// don't wait
			}

			// check for user input
			struct pollfd fds {};
			fds.fd = 0; /* stdin */
			fds.events = POLLIN;

			if (poll(&fds, 1, 0) > 0) {

				char c = 0;
				int ret = read(0, &c, user_input_timeout);

				if (ret) {
					return;
				}

				switch (c) {
				case 0x03: // ctrl-c
				case 0x1b: // esc
				case 'q':
					return;
					/* not reached */
				}
			}

			if (updated) {
				start_time = hrt_absolute_time();
				i++;

				PX4_INFO_RAW("\nTOPIC: %s instance %d #%d\n", id->o_name, topic_instance, i);

				int ret = cb(id, sub);

				if (ret != PX4_OK) {
					PX4_ERR("listener callback failed (%i)", ret);
				}

			} else {
				if (hrt_elapsed_time(&start_time) > 2 * 1000 * 1000) {
					PX4_INFO_RAW("Waited for 2 seconds without a message. Giving up.\n");
					break;
				}
			}
		}

		orb_unsubscribe(sub);
	}

}

int listener_main(int argc, char *argv[])
{
	if (argc <= 1) {
		usage();
		return 1;
	}

	char *topic_name = argv[1];

	int topic_instance = -1;
	unsigned topic_rate = 0;
	unsigned num_msgs = 0;

	int myoptind = 1;
	int ch;
	const char *myoptarg = nullptr;

	while ((ch = px4_getopt(argc, argv, "i:r:n:", &myoptind, &myoptarg)) != EOF) {
		switch (ch) {

		case 'i':
			topic_instance = strtol(myoptarg, nullptr, 0);
			break;

		case 'r':
			topic_rate = strtol(myoptarg, nullptr, 0);
			break;

		case 'n':
			num_msgs = strtol(myoptarg, nullptr, 0);
			break;

		default:
			usage();
			return -1;
			break;
		}
	}

	if (num_msgs == 0) {
		if (topic_rate != 0) {
			num_msgs = 30 * topic_rate; // arbitrary limit (30 seconds at max rate)

		} else {
			num_msgs = 1;
		}
	}

	listener_generated(topic_name, topic_instance, topic_rate, num_msgs);

	return 0;
}

static void
usage()
{
	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
Utility to listen on uORB topics and print the data to the console.

The listener can be exited any time by pressing Ctrl+C, Esc, or Q.
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("listener", "command");
	PRINT_MODULE_USAGE_ARG("<topic_name>", "uORB topic name", false);

	PRINT_MODULE_USAGE_PARAM_INT('i', 0, 0, ORB_MULTI_MAX_INSTANCES - 1, "Topic instance", true);
	PRINT_MODULE_USAGE_PARAM_INT('n', 1, 0, 100, "Number of messages", true);
	PRINT_MODULE_USAGE_PARAM_INT('r', 0, 0, 1000, "Subscription rate (unlimited if 0)", true);
}
<commit_msg>listener fix incorrect "never published" cases (#13006)<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file listener_main.cpp
 *
 * Tool for listening to topics.
 */

#include <px4_module.h>
#include <px4_getopt.h>

#include <poll.h>

#include "topic_listener.hpp"
#include "topic_listener_generated.hpp"

extern "C" __EXPORT int listener_main(int argc, char *argv[]);

static void usage();

void listener(listener_print_topic_cb cb, const orb_id_t &id, unsigned num_msgs, int topic_instance,
	      unsigned topic_interval)
{

	if (topic_instance == -1 && num_msgs == 1) {
		// first count the number of instances
		int instances = 0;

		for (int i = 0; i < ORB_MULTI_MAX_INSTANCES; i++) {
			if (orb_exists(id, i) == PX4_OK) {
				instances++;
			}
		}

		if (instances == 1) {
			PX4_INFO_RAW("\nTOPIC: %s\n", id->o_name);
			int sub = orb_subscribe(id);
			cb(id, sub);
			orb_unsubscribe(sub);

		} else if (instances > 1) {
			PX4_INFO_RAW("\nTOPIC: %s %d instances\n", id->o_name, instances);

			for (int i = 0; i < ORB_MULTI_MAX_INSTANCES; i++) {
				if (orb_exists(id, i) == PX4_OK) {
					PX4_INFO_RAW("\nInstance %d:\n", i);
					int sub = orb_subscribe_multi(id, i);
					cb(id, sub);
					orb_unsubscribe(sub);
				}
			}
		}

		if (instances == 0) {
			PX4_INFO_RAW("never published\n");
		}

	} else {
		// default to the first instance if not specified
		if (topic_instance == -1) {
			topic_instance = 0;
		}

		if (orb_exists(id, topic_instance) != 0) {
			PX4_INFO_RAW("never published\n");
			return;
		}

		int sub = orb_subscribe_multi(id, topic_instance);
		orb_set_interval(sub, topic_interval);

		bool updated = false;
		unsigned i = 0;
		hrt_abstime start_time = hrt_absolute_time();

		while (i < num_msgs) {

			// check for user input to quit
			int user_input_timeout = 1;

			orb_check(sub, &updated);

			if (i == 0) {
				updated = true;
				user_input_timeout = 0;	// don't wait
			}

			// check for user input
			struct pollfd fds {};
			fds.fd = 0; /* stdin */
			fds.events = POLLIN;

			if (poll(&fds, 1, 0) > 0) {

				char c = 0;
				int ret = read(0, &c, user_input_timeout);

				if (ret) {
					return;
				}

				switch (c) {
				case 0x03: // ctrl-c
				case 0x1b: // esc
				case 'q':
					return;
					/* not reached */
				}
			}

			if (updated) {
				start_time = hrt_absolute_time();
				i++;

				PX4_INFO_RAW("\nTOPIC: %s instance %d #%d\n", id->o_name, topic_instance, i);

				int ret = cb(id, sub);

				if (ret != PX4_OK) {
					PX4_ERR("listener callback failed (%i)", ret);
				}

			} else {
				if (hrt_elapsed_time(&start_time) > 2 * 1000 * 1000) {
					PX4_INFO_RAW("Waited for 2 seconds without a message. Giving up.\n");
					break;
				}
			}
		}

		orb_unsubscribe(sub);
	}

}

int listener_main(int argc, char *argv[])
{
	if (argc <= 1) {
		usage();
		return 1;
	}

	char *topic_name = argv[1];

	int topic_instance = -1;
	unsigned topic_rate = 0;
	unsigned num_msgs = 0;

	int myoptind = 1;
	int ch;
	const char *myoptarg = nullptr;

	while ((ch = px4_getopt(argc, argv, "i:r:n:", &myoptind, &myoptarg)) != EOF) {
		switch (ch) {

		case 'i':
			topic_instance = strtol(myoptarg, nullptr, 0);
			break;

		case 'r':
			topic_rate = strtol(myoptarg, nullptr, 0);
			break;

		case 'n':
			num_msgs = strtol(myoptarg, nullptr, 0);
			break;

		default:
			usage();
			return -1;
			break;
		}
	}

	if (num_msgs == 0) {
		if (topic_rate != 0) {
			num_msgs = 30 * topic_rate; // arbitrary limit (30 seconds at max rate)

		} else {
			num_msgs = 1;
		}
	}

	listener_generated(topic_name, topic_instance, topic_rate, num_msgs);

	return 0;
}

static void
usage()
{
	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
Utility to listen on uORB topics and print the data to the console.

The listener can be exited any time by pressing Ctrl+C, Esc, or Q.
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("listener", "command");
	PRINT_MODULE_USAGE_ARG("<topic_name>", "uORB topic name", false);

	PRINT_MODULE_USAGE_PARAM_INT('i', 0, 0, ORB_MULTI_MAX_INSTANCES - 1, "Topic instance", true);
	PRINT_MODULE_USAGE_PARAM_INT('n', 1, 0, 100, "Number of messages", true);
	PRINT_MODULE_USAGE_PARAM_INT('r', 0, 0, 1000, "Subscription rate (unlimited if 0)", true);
}
<|endoftext|>


<commit_before>#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

#include <fj_tool/fapp.h>
#include <fjcoll.h>

#include "pearson-3d.h"

int T_MAX;
int T_MONITOR;
int mpi_my_rank;
const double PI=3.14159265358979323846;

float frand() {
  return rand() / float(RAND_MAX);
}

double wctime() {
  struct timeval tv;
  gettimeofday(&tv,NULL);
  return (double)tv.tv_sec + (double)tv.tv_usec*1e-6;
}

void init() {
  for(int ix = navi.lower_x; ix < navi.upper_x; ++ix) {
    for(int iy = navi.lower_y; iy < navi.upper_y; ++iy) {
      for(int iz = navi.lower_z; iz < navi.upper_z; ++iz) {
        double k = (2*PI) / fmin(NX,fmin(NY,NZ));
        double x = k * (navi.offset_x + ix);
        double y = k * (navi.offset_y + iy);
        double z = k * (navi.offset_z + iz);
        U[ix][iy][iz] = 1.0;
        V[ix][iy][iz] = 0.0;
        if (sin(x) * sin(y) * sin(z) > 0.9) {
          U[ix][iy][iz] = 0.5;
          V[ix][iy][iz] = 0.25;
        }
      }
    }
  }
}

void write_monitor() {
  printf("#%d: t = %d\n", mpi_my_rank, navi.time_step);
  char fn[256];
  sprintf(fn, "out/monitor-%06d-%d.txt", navi.time_step, mpi_my_rank);
  FILE *fp = fopen(fn,"wb");
  int global_position[6];
  global_position[0] = navi.offset_x + navi.lower_x;
  global_position[1] = navi.offset_y + navi.lower_y;
  global_position[2] = navi.offset_z + navi.lower_z;
  global_position[3] = navi.upper_x - navi.lower_x;
  global_position[4] = navi.upper_y - navi.lower_y;
  global_position[5] = navi.upper_z - navi.lower_z;
  fwrite(global_position, sizeof(int), 6, fp);

  int x_size = navi.upper_x - navi.lower_x;
  int y_size = navi.upper_y - navi.lower_y;
  int z_size = navi.upper_z - navi.lower_z;
  {
    const int y=navi.lower_y + y_size/2;
    for(int x = navi.lower_x; x < navi.upper_x; ++x) fwrite(U[x][y]+navi.lower_z, sizeof(double),z_size, fp);
    for(int x = navi.lower_x; x < navi.upper_x; ++x) fwrite(V[x][y]+navi.lower_z, sizeof(double),z_size, fp);
  }
  {
    const int x=navi.lower_x + x_size/2;
    for(int y = navi.lower_y; y < navi.upper_y; ++y) fwrite(U[x][y]+navi.lower_z, sizeof(double),z_size, fp);
    for(int y = navi.lower_y; y < navi.upper_y; ++y) fwrite(V[x][y]+navi.lower_z, sizeof(double),z_size, fp);
  }
  fclose(fp);
}

int main (int argc, char **argv) {
  srand(time(NULL));
  MPI_Init(&argc, &argv);
  Formura_Init(&navi, MPI_COMM_WORLD);
  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_my_rank);

  if (argc <= 1) {
    T_MAX=1024;
  }else{
    sscanf(argv[1], "%d",  &T_MAX);
  }
  if (argc <= 2) {
    T_MONITOR=1024;
  }else{
    sscanf(argv[2], "%d",  &T_MONITOR);
  }

  init();

  double t_begin = wctime(), t_end;

  for(;;){
    double t = wctime();
    if(navi.time_step % T_MONITOR == 0 || navi.time_step <= 3 * T_MONITOR ) {
      printf("%d step @ %lf sec\n", navi.time_step, t-t_begin);
    }
    if(navi.time_step % T_MONITOR == 0) {
      write_monitor();
    }

    if (navi.time_step >= T_MAX) break;
    if (navi.time_step == 0) {
      t_begin = wctime();
      start_collection("main");
    }

    Formura_Forward(&navi); // navi.time_step increases
    MPI_Barrier(MPI_COMM_WORLD); // TODO: test the effect of synchronization

    if (navi.time_step >= T_MAX) {
      t_end = wctime();
      stop_collection("main");
    }
  }
  printf("wct = %lf sec\n",t_end - t_begin);

  MPI_Barrier(MPI_COMM_WORLD);
  MPI_Finalize();
}
<commit_msg>Add random phase perturbation<commit_after>#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

#include <fj_tool/fapp.h>
#include <fjcoll.h>

#include "pearson-3d.h"

int T_MAX;
int T_MONITOR;
int mpi_my_rank;
const double PI=3.14159265358979323846;

float frand() {
  return rand() / float(RAND_MAX);
}

double wctime() {
  struct timeval tv;
  gettimeofday(&tv,NULL);
  return (double)tv.tv_sec + (double)tv.tv_usec*1e-6;
}

void init() {
  double wx = frand() * 2 * PI;
  double wy = frand() * 2 * PI;
  double wz = frand() * 2 * PI;
  for(int ix = navi.lower_x; ix < navi.upper_x; ++ix) {
    for(int iy = navi.lower_y; iy < navi.upper_y; ++iy) {
      for(int iz = navi.lower_z; iz < navi.upper_z; ++iz) {
        double k = (2*PI) / fmin(NX,fmin(NY,NZ));
        double x = k * (navi.offset_x + ix);
        double y = k * (navi.offset_y + iy);
        double z = k * (navi.offset_z + iz);
        U[ix][iy][iz] = 1.0;
        V[ix][iy][iz] = 0.0;
        if (sin(x+wx) * sin(y+wy) * sin(z+wz) > 0.9) {
          U[ix][iy][iz] = 0.5;
          V[ix][iy][iz] = 0.25;
        }
      }
    }
  }
}

void write_monitor() {
  printf("#%d: t = %d\n", mpi_my_rank, navi.time_step);
  char fn[256];
  sprintf(fn, "out/monitor-%06d-%d.txt", navi.time_step, mpi_my_rank);
  FILE *fp = fopen(fn,"wb");
  int global_position[6];
  global_position[0] = navi.offset_x + navi.lower_x;
  global_position[1] = navi.offset_y + navi.lower_y;
  global_position[2] = navi.offset_z + navi.lower_z;
  global_position[3] = navi.upper_x - navi.lower_x;
  global_position[4] = navi.upper_y - navi.lower_y;
  global_position[5] = navi.upper_z - navi.lower_z;
  fwrite(global_position, sizeof(int), 6, fp);

  int x_size = navi.upper_x - navi.lower_x;
  int y_size = navi.upper_y - navi.lower_y;
  int z_size = navi.upper_z - navi.lower_z;
  {
    const int y=navi.lower_y + y_size/2;
    for(int x = navi.lower_x; x < navi.upper_x; ++x) fwrite(U[x][y]+navi.lower_z, sizeof(double),z_size, fp);
    for(int x = navi.lower_x; x < navi.upper_x; ++x) fwrite(V[x][y]+navi.lower_z, sizeof(double),z_size, fp);
  }
  {
    const int x=navi.lower_x + x_size/2;
    for(int y = navi.lower_y; y < navi.upper_y; ++y) fwrite(U[x][y]+navi.lower_z, sizeof(double),z_size, fp);
    for(int y = navi.lower_y; y < navi.upper_y; ++y) fwrite(V[x][y]+navi.lower_z, sizeof(double),z_size, fp);
  }
  fclose(fp);
}

int main (int argc, char **argv) {
  srand(time(NULL));
  MPI_Init(&argc, &argv);
  Formura_Init(&navi, MPI_COMM_WORLD);
  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_my_rank);

  if (argc <= 1) {
    T_MAX=1024;
  }else{
    sscanf(argv[1], "%d",  &T_MAX);
  }
  if (argc <= 2) {
    T_MONITOR=1024;
  }else{
    sscanf(argv[2], "%d",  &T_MONITOR);
  }

  init();

  double t_begin = wctime(), t_end;

  for(;;){
    double t = wctime();
    if(navi.time_step % T_MONITOR == 0 || navi.time_step <= 3 * T_MONITOR ) {
      printf("%d step @ %lf sec\n", navi.time_step, t-t_begin);
    }
    if(navi.time_step % T_MONITOR == 0) {
      write_monitor();
    }

    if (navi.time_step >= T_MAX) break;
    if (navi.time_step == 0) {
      t_begin = wctime();
      start_collection("main");
    }

    Formura_Forward(&navi); // navi.time_step increases
    MPI_Barrier(MPI_COMM_WORLD); // TODO: test the effect of synchronization

    if (navi.time_step >= T_MAX) {
      t_end = wctime();
      stop_collection("main");
    }
  }
  printf("wct = %lf sec\n",t_end - t_begin);

  MPI_Barrier(MPI_COMM_WORLD);
  MPI_Finalize();
}
<|endoftext|>


<commit_before>#ifndef FIX_TERMS_HPP_
#define FIX_TERMS_HPP_
#include "basics.hpp"

#include <algorithm>
#include <cmath>
#include <vector>

namespace NPDivs {

template <typename T>
bool cmp_with_inf(T i, T j) { return std::isinf(i) || i < j; }

template <typename T>
struct greater_than {
    greater_than(T x) : base(x) {}
    bool operator()(T y) { return y > base; }

    private:
        T base;
};

template <typename T>
void fix_terms(std::vector<T> &terms, double ub = .99) {
    /* Takes a vector of elements and replaces any infinite or very-large
     * elements with the value of the highest non-very-large element, as well
     * as throwing away any nan values, possibly changing the order.
     * "Very-large" is defined as the ub-th quantile if ub < 1, otherwise the
     * largest non-inf element. Note that values of -inf are not altered.
     */
    typedef typename std::vector<T>::size_type sz;

    using std::max_element;
    using std::nth_element;
    using std::replace_if;
    using std::remove_if;

    T cutoff;
    bool find_noninf_max = true;

    // throw away any nans
    remove_if(terms.begin(), terms.end(), std::isnan<T>);

    // try finding the ub-th percentile
    if (ub < 1) {
        sz k = (sz) (terms.size() * ub); // the index we want
        nth_element(terms.begin(), terms.begin() + k, terms.end());
        cutoff = terms[k];

        find_noninf_max = std::isinf(cutoff);
    }

    // just use the highest non-inf element
    if (find_noninf_max) {
        cutoff = *max_element(terms.begin(), terms.end(), cmp_with_inf<T>);
    }

    // replace anything greater than cutoff with cutoff
    replace_if(terms.begin(), terms.end(), greater_than<T>(cutoff), cutoff);
}

}

#endif
<commit_msg>fix_terms: use same method as matlab, fix some bugs<commit_after>#ifndef FIX_TERMS_HPP_
#define FIX_TERMS_HPP_
#include "basics.hpp"

#include <algorithm>
#include <cmath>
#include <vector>

namespace NPDivs {

template <typename T>
bool cmp_with_inf(T i, T j) {
    if (std::isinf(i)) return true;
    else if (std::isinf(j)) return false;
    else return i < j;
}

template <typename T>
struct greater_than {
    greater_than(T x) : base(x) {}
    bool operator()(T y) { return y > base; }

    private:
        T base;
};

template <typename T>
T quantile(std::vector<T> &vec, double p) {
    /* Finds the p-th quantile of vec, changing its order in doing so
     * (unless it's already sorted). Assumes that vec contains no nan
     * values.
     *
     * Like the MATLAB quantile() function, but for only a single p.
     * Specifically:
     *
     * Quantiles are specified using cumulative probabilities from 0 to 1. For
     * an n-element vector vec, quantile computes quantiles as follows:
     *
     * 1. The sorted values in vec are taken as the
     *      (0.5/n), (1.5/n), ..., ([n–0.5]/n) quantiles.
     *
     * 2. Linear interpolation is used to compute quantiles for probabilities
     *      between (0.5/n) and ([n–0.5]/n).
     *
     * 3. The minimum or maximum values in vec are assigned to quantiles for
     *      probabilities outside that range.
     */
    typedef typename std::vector<T>::size_type sz;

    sz n = vec.size();

    if (p > (n-.5) / n) {
        return *std::max_element(vec.begin(), vec.end());

    } else if (p < .5 / n) {
        return *std::min_element(vec.begin(), vec.end());

    } else {
        // find the bounds we're interpolating between
        // that is, find i s.t. (i+.5) / n <= p < (i+1.5)/n
        double t = n * p - .5;
        sz i = (sz) std::floor(t);

        // partial sort so that the ith element is in vec[i], with
        // smaller indices below it and larger above
        std::nth_element(vec.begin(), vec.begin() + i, vec.end());

        if (i == t) {
            // did we luck out and get an integer index?
            return vec[i];

        } else {
            // do linear interpolation between this and next index
            T smaller = vec[i];

            // figure out what next index is
            T larger = *std::min_element(vec.begin() + i + 1, vec.end());

            // interpolate
            return smaller + (larger - smaller) * (t - i);
        }
    }
}

template <typename T>
void fix_terms(std::vector<T> &terms, double ub = .99) {
    /* Takes a vector of elements and replaces any infinite or very-large
     * elements with the value of the highest non-very-large element, as well
     * as throwing away any nan values, possibly changing the order.
     * "Very-large" is defined as the ub-th quantile if ub < 1, otherwise the
     * largest non-inf element. Note that values of -inf are not altered.
     */
    typedef typename std::vector<T>::size_type sz;

    using std::max_element;
    using std::nth_element;
    using std::replace_if;
    using std::remove_if;

    T cutoff;
    bool find_noninf_max = true;

    // throw away any nans
    terms.erase(remove_if(terms.begin(), terms.end(), std::isnan<T>),
                terms.end());

    // try finding the ub-th percentile
    if (ub < 1) {
        cutoff = quantile(terms, ub);
        find_noninf_max = std::isinf(cutoff) || std::isnan(cutoff);
    }

    // just use the highest non-inf element
    if (find_noninf_max) {
        cutoff = *max_element(terms.begin(), terms.end(), cmp_with_inf<T>);
    }

    // replace anything greater than cutoff with cutoff
    replace_if(terms.begin(), terms.end(), greater_than<T>(cutoff), cutoff);
}

}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 Andrew Sutton
// All rights reserved

#include "prelude.hpp"
#include "equivalence.hpp"

#include <boost/functional/hash.hpp>

namespace banjo
{

std::size_t hash_value(Name const&);
std::size_t hash_value(Type const&);
std::size_t hash_value(Expr const&);
std::size_t hash_value(Decl const&);
std::size_t hash_value(Cons const&);

template<typename T>
struct Term_hash
{
  bool operator()(T const* t) const
  {
    return hash_value(*t);
  }
};

using Name_hash = Term_hash<Name>;
using Type_hash = Term_hash<Type>;
using Expr_hash = Term_hash<Expr>;
using Cons_hash = Term_hash<Cons>;

} // namespace banjo
<commit_msg>Somebody forgot header sentries on hash.hpp.<commit_after>// Copyright (c) 2015-2016 Andrew Sutton
// All rights reserved

#ifndef BANJO_HASH_HPP
#define BANJO_HASH_HPP

#include "prelude.hpp"
#include "equivalence.hpp"

#include <boost/functional/hash.hpp>

namespace banjo
{

std::size_t hash_value(Name const&);
std::size_t hash_value(Type const&);
std::size_t hash_value(Expr const&);
std::size_t hash_value(Decl const&);
std::size_t hash_value(Cons const&);

template<typename T>
struct Term_hash
{
  bool operator()(T const* t) const
  {
    return hash_value(*t);
  }
};

using Name_hash = Term_hash<Name>;
using Type_hash = Term_hash<Type>;
using Expr_hash = Term_hash<Expr>;
using Cons_hash = Term_hash<Cons>;

} // namespace banjo

#endif
<|endoftext|>


<commit_before>#include "VertexAttributeBindingImplementation_Legacy.h"

#include <cassert>

#include <glbinding/gl/functions.h>
#include <glbinding/gl/enum.h>

#include <globjects/Buffer.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>

using namespace gl;

namespace globjects
{

VertexAttributeBindingImplementation_Legacy::Format::Format()
: method(Method::O)
, size(0)
, type(GL_INVALID_ENUM)
, normalized(GL_FALSE)
, relativeoffset(0)
{
}

VertexAttributeBindingImplementation_Legacy::Format::Format(
    VertexAttributeBindingImplementation_Legacy::Format::Method method, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
: method(method)
, size(size)
, type(type)
, normalized(normalized)
, relativeoffset(relativeoffset)
{
}

VertexAttributeBindingImplementation_Legacy::BindingData::BindingData()
: baseoffset(0)
, stride(0)
, hasFormat(false)
, hasBuffer(false)
, hasAttribute(false)
{
}

VertexAttributeBindingImplementation_Legacy::VertexAttributeBindingImplementation_Legacy()
{
}

VertexAttributeBindingImplementation_Legacy::~VertexAttributeBindingImplementation_Legacy()
{
}

void VertexAttributeBindingImplementation_Legacy::enable(const VertexArray * vertexArray, GLint attributeIndex) const
{
    vertexArray->bind();

    glEnableVertexAttribArray(attributeIndex);
}

void VertexAttributeBindingImplementation_Legacy::disable(const VertexArray * vertexArray, GLint attributeIndex) const
{
    vertexArray->bind();

    glDisableVertexAttribArray(attributeIndex);
}

void VertexAttributeBindingImplementation_Legacy::setAttributeDivisor(const VertexAttributeBinding * binding, GLuint divisor) const
{
    vao(binding)->bind();

    glVertexAttribDivisor(binding->attributeIndex(), divisor);
}

VertexAttributeBindingImplementation_Legacy::BindingData * & VertexAttributeBindingImplementation_Legacy::bindingData(const VertexAttributeBinding * binding) const
{
    return reinterpret_cast<BindingData * &>(AbstractVertexAttributeBindingImplementation::bindingData(binding));
}

void VertexAttributeBindingImplementation_Legacy::bindAttribute(const VertexAttributeBinding * binding, GLint /*attributeIndex*/) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->hasAttribute = true;
    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::bindBuffer(const VertexAttributeBinding * binding, const Buffer * /*vbo*/, GLint baseoffset, GLint stride) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->baseoffset = baseoffset;
    bindingData(binding)->stride = stride;
    bindingData(binding)->hasBuffer = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::O, size, type, normalized, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setIFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::I, size, type, GL_FALSE, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setLFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::L, size, type, GL_FALSE, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::finishIfComplete(const VertexAttributeBinding * binding) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    if (bindingData(binding)->hasAttribute && bindingData(binding)->hasFormat && bindingData(binding)->hasBuffer)
        finish(binding);
}

void VertexAttributeBindingImplementation_Legacy::finish(const VertexAttributeBinding * binding) const
{
    assert(bindingData(binding) != nullptr);

    vao(binding)->bind();

    void * offset = nullptr;

    if (vbo(binding))
    {
        vbo(binding)->bind(GL_ARRAY_BUFFER);
        offset = reinterpret_cast<void *>(bindingData(binding)->baseoffset + bindingData(binding)->format.relativeoffset);
    }
    else
    {
        Buffer::unbind(GL_ARRAY_BUFFER);
    }

    const GLint attribute = attributeIndex(binding);

    switch (bindingData(binding)->format.method)
    {
    case Format::Method::I:
        glVertexAttribIPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->stride, offset);
        break;

    case Format::Method::L:
        glVertexAttribLPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->stride, offset);
        break;

    default:
        glVertexAttribPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->format.normalized, bindingData(binding)->stride, offset);
    }
}

} // namespace globjects
<commit_msg>fix cast<commit_after>#include "VertexAttributeBindingImplementation_Legacy.h"

#include <cassert>

#include <glbinding/gl/functions.h>
#include <glbinding/gl/enum.h>

#include <globjects/Buffer.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>

using namespace gl;

namespace globjects
{

VertexAttributeBindingImplementation_Legacy::Format::Format()
: method(Method::O)
, size(0)
, type(GL_INVALID_ENUM)
, normalized(GL_FALSE)
, relativeoffset(0)
{
}

VertexAttributeBindingImplementation_Legacy::Format::Format(
    VertexAttributeBindingImplementation_Legacy::Format::Method method, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
: method(method)
, size(size)
, type(type)
, normalized(normalized)
, relativeoffset(relativeoffset)
{
}

VertexAttributeBindingImplementation_Legacy::BindingData::BindingData()
: baseoffset(0)
, stride(0)
, hasFormat(false)
, hasBuffer(false)
, hasAttribute(false)
{
}

VertexAttributeBindingImplementation_Legacy::VertexAttributeBindingImplementation_Legacy()
{
}

VertexAttributeBindingImplementation_Legacy::~VertexAttributeBindingImplementation_Legacy()
{
}

void VertexAttributeBindingImplementation_Legacy::enable(const VertexArray * vertexArray, GLint attributeIndex) const
{
    vertexArray->bind();

    glEnableVertexAttribArray(attributeIndex);
}

void VertexAttributeBindingImplementation_Legacy::disable(const VertexArray * vertexArray, GLint attributeIndex) const
{
    vertexArray->bind();

    glDisableVertexAttribArray(attributeIndex);
}

void VertexAttributeBindingImplementation_Legacy::setAttributeDivisor(const VertexAttributeBinding * binding, GLuint divisor) const
{
    vao(binding)->bind();

    glVertexAttribDivisor(binding->attributeIndex(), divisor);
}

VertexAttributeBindingImplementation_Legacy::BindingData * & VertexAttributeBindingImplementation_Legacy::bindingData(const VertexAttributeBinding * binding) const
{
    return reinterpret_cast<BindingData * &>(AbstractVertexAttributeBindingImplementation::bindingData(binding));
}

void VertexAttributeBindingImplementation_Legacy::bindAttribute(const VertexAttributeBinding * binding, GLint /*attributeIndex*/) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->hasAttribute = true;
    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::bindBuffer(const VertexAttributeBinding * binding, const Buffer * /*vbo*/, GLint baseoffset, GLint stride) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->baseoffset = baseoffset;
    bindingData(binding)->stride = stride;
    bindingData(binding)->hasBuffer = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::O, size, type, normalized, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setIFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::I, size, type, GL_FALSE, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::setLFormat(const VertexAttributeBinding * binding, GLint size, GLenum type, GLuint relativeoffset) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    bindingData(binding)->format = Format(Format::Method::L, size, type, GL_FALSE, relativeoffset);
    bindingData(binding)->hasFormat = true;

    finishIfComplete(binding);
}

void VertexAttributeBindingImplementation_Legacy::finishIfComplete(const VertexAttributeBinding * binding) const
{
    if (bindingData(binding) == nullptr)
        bindingData(binding) = new BindingData();

    if (bindingData(binding)->hasAttribute && bindingData(binding)->hasFormat && bindingData(binding)->hasBuffer)
        finish(binding);
}

void VertexAttributeBindingImplementation_Legacy::finish(const VertexAttributeBinding * binding) const
{
    assert(bindingData(binding) != nullptr);

    vao(binding)->bind();

    void * offset = nullptr;

    if (vbo(binding))
    {
        vbo(binding)->bind(GL_ARRAY_BUFFER);
        const auto offset64 = static_cast<GLuint64>(bindingData(binding)->baseoffset + bindingData(binding)->format.relativeoffset);
        offset = reinterpret_cast<void *>(offset64);
    }
    else
    {
        Buffer::unbind(GL_ARRAY_BUFFER);
    }

    const GLint attribute = attributeIndex(binding);

    switch (bindingData(binding)->format.method)
    {
    case Format::Method::I:
        glVertexAttribIPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->stride, offset);
        break;

    case Format::Method::L:
        glVertexAttribLPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->stride, offset);
        break;

    default:
        glVertexAttribPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type
            , bindingData(binding)->format.normalized, bindingData(binding)->stride, offset);
    }
}

} // namespace globjects
<|endoftext|>


<commit_before>#include <stdlib.h>
#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "braincloud/BrainCloudEntity.h"
#include "TestResult.h"
#include "json/json.h"
#include "TestBCEntity.h"
#include "braincloud/reason_codes.h"
#include "braincloud/http_codes.h"

using namespace BrainCloud;

TEST_F(TestBCEntity, Create)
{
	TestResult tr;

	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc))
	{
		m_entityId = tr.m_response["data"]["entityId"].asString();
		ASSERT_NE("", m_entityId);
	}

	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, Update)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	CreateDefaultEntity();

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateEntity(m_entityId.c_str(), m_entityType, fw.write(entityData), "", -1, &tr);
	tr.run(m_bc);

	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, BadUpdate)
{
	TestResult tr;
	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";
	std::string badEntityId = "wakawaka";

	Json::FastWriter fw;
	m_bc->getEntityService()->updateEntity(badEntityId.c_str(), m_entityType, fw.write(entityData), "", -1, &tr);
	// TODO : put in the correct error code constant
	tr.runExpectFail(m_bc, HTTP_NOT_FOUND, 40332);
}

TEST_F(TestBCEntity, Delete)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->deleteEntity(m_entityId.c_str(), -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCEntity, GetEntity)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getEntity(m_entityId.c_str(), &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, GetSingleton)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getSingleton(m_entityType, &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TEST_F(TestBCEntity, GetSharedEntityForPlayerId)
{
	TestResult tr;
	CreateDefaultEntity();
	m_bc->getEntityService()->getSharedEntityForPlayerId(GetUser(UserA)->m_profileId, m_entityId.c_str(), &tr);
	tr.run(m_bc);
	DeleteEntity();
}
#pragma clang diagnostic pop

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TEST_F(TestBCEntity, GetSharedEntitiesForPlayerId)
{
	TestResult tr;
	CreateDefaultEntity();
	m_bc->getEntityService()->getSharedEntitiesForPlayerId(GetUser(UserA)->m_profileId, &tr);
	tr.run(m_bc);
	DeleteEntity();
}
#pragma clang diagnostic pop

TEST_F(TestBCEntity, GetEntitesByType)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getEntitiesByType(m_entityType, &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, DeleteSingleton)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->deleteSingleton(m_entityType, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCEntity, UpdateSharedEntity)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	CreateDefaultEntity();

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateSharedEntity(m_entityId.c_str(), GetUser(UserA)->m_profileId, m_entityType, fw.write(entityData), -1, &tr);
	tr.run(m_bc);

	DeleteEntity();
}

TEST_F(TestBCEntity, UpdateSingleton)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateSingleton(m_entityType, fw.write(entityData), "", -1, &tr);
	tr.run(m_bc);

	DeleteEntity();
}

TEST_F(TestBCEntity, GetList)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value whereJson;
	whereJson["entityType"] = m_entityType;

	m_bc->getEntityService()->getList(fw.write(whereJson), "", 100, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetSharedEntitiesListForPlayerId)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value whereJson;
	whereJson["entityType"] = m_entityType;

	m_bc->getEntityService()->getSharedEntitiesListForPlayerId(
		GetUser(UserA)->m_profileId,
		fw.write(whereJson), "", 100, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetListCount)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value searchType;
	searchType["entityType"] = m_entityType;
	std::string searchTypeStr = fw.write(searchType);

	m_bc->getEntityService()->getListCount(searchTypeStr, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetPage)
{
	GenerateDefaultEntites(20);

	Json::Value context;
	Json::FastWriter fw;

	context["pagination"]["rowsPerPage"] = 12;
	context["pagination"]["pageNumber"] = 1;
	context["searchCriteria"]["entityType"] = m_entityType;

	TestResult tr;
	m_bc->getEntityService()->getPage(fw.write(context).c_str(), &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetPageOffset)
{
	GenerateDefaultEntites(20);

	Json::Value context;
	Json::FastWriter fw;

	context["pagination"]["rowsPerPage"] = 12;
	context["pagination"]["pageNumber"] = 1;
	context["searchCriteria"]["entityType"] = m_entityType;

	TestResult tr;
	m_bc->getEntityService()->getPage(fw.write(context).c_str(), &tr);
	tr.run(m_bc);

	std::string context_str = tr.m_response["data"]["context"].asString();

	tr.reset();
	m_bc->getEntityService()->getPageOffset(context_str.c_str(), 1, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, IncrementUserEntityData)
{
	TestResult tr;
	Json::Value entityData;
	entityData["test"] = 1233;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc)) entityId = tr.m_response["data"]["entityId"].asString();

	m_bc->getEntityService()->incrementUserEntityData(entityId.c_str(), fw.write(entityData), &tr);
	tr.run(m_bc);

	DeleteEntity(entityId);
}

TEST_F(TestBCEntity, IncrementSharedUserEntityData)
{
	TestResult tr;
	Json::Value entityData;
	entityData["test"] = 1233;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc)) entityId = tr.m_response["data"]["entityId"].asString();

	m_bc->getEntityService()->incrementSharedUserEntityData(entityId.c_str(), GetUser(UserA)->m_profileId, fw.write(entityData), &tr);
	tr.run(m_bc);

	DeleteEntity(entityId);
}

void TestBCEntity::CreateDefaultEntity()
{
	TestResult tr;
	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";
	Json::Value entityAcl;
	entityAcl["other"] = 2;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), fw.write(entityAcl), &tr);
	if (tr.run(m_bc))
	{
		m_entityId = tr.m_response["data"]["entityId"].asString();
	}
}

void TestBCEntity::DeleteEntity(std::string entityId)
{
	if (entityId.length() <= 0) entityId = m_entityId;
	TestResult tr;
	m_bc->getEntityService()->deleteEntity(entityId.c_str(), -1, &tr);
	tr.run(m_bc);
}

void TestBCEntity::GenerateDefaultEntites(int numToGenerate)
{
	TestResult tr;

	Json::FastWriter fw;
	Json::Value searchType;
	searchType["entityType"] = m_entityType;
	std::string searchTypeStr = fw.write(searchType);

	for (int i = 0; i < numToGenerate; i++) {
		CreateDefaultEntity();
	}
}

void TestBCEntity::DeleteAllDefaultEntities()
{
	TestResult tr;
	m_bc->getEntityService()->getEntitiesByType(m_entityType, &tr);
	if (tr.run(m_bc))
	{
		Json::Value entityArray = tr.m_response["data"]["entities"];

		/* for some reason, marmalade goes past entityArray.end() so we do this via indices
		Json::Value::iterator it;
		for (it = entityArray.begin(); it !=entityArray.end(); ++it)
		{
		Json::Value key = it.key(); // why get this?
		Json::Value value = (*it);

		DeleteEntity(value["entityId"].asString());
		}
		*/

		for (int i = 0, isize = entityArray.size(); i < isize; ++i)
		{
			Json::Value value = entityArray[i];
			DeleteEntity(value["entityId"].asString());
		}
		m_entityId = tr.m_response["data"]["entityId"].asString();
	}
}

/*
 TEST_F(TestBCTime, LargePacket)
 {
 TestResult tr;

 std::vector<int> hugeTimeout;
 hugeTimeout.push_back(180);
 m_bc->setPacketTimeouts(hugeTimeout);

 Json::Value entityData;
 int mbs = 1;
 for (int i = 0; i < mbs; ++i)
 {
 std::ostringstream oss;
 oss << i;
 std::string key = oss.str();
 oss.clear();
 for (int j = 0; j < (1024/8)*1024; ++j)
 {
 oss << "01234567";
 }
 std::string data = oss.str();
 entityData[key] = data;
 }
 Json::FastWriter fw;
 m_bc->getEntityService()->createEntity("largepacket", fw.write(entityData), "", &tr);
 if (tr.run(m_bc))
 {
 // m_entityId = tr.m_response["data"]["entityId"].asString();
 // ASSERT_NE("", m_entityId);
 }

 m_bc->setPacketTimeoutsToDefault();
 }
 */

<commit_msg>test fix, needed to pass in entityId<commit_after>#include <stdlib.h>
#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "braincloud/BrainCloudEntity.h"
#include "TestResult.h"
#include "json/json.h"
#include "TestBCEntity.h"
#include "braincloud/reason_codes.h"
#include "braincloud/http_codes.h"

using namespace BrainCloud;

TEST_F(TestBCEntity, Create)
{
	TestResult tr;

	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc))
	{
		m_entityId = tr.m_response["data"]["entityId"].asString();
		ASSERT_NE("", m_entityId);
	}

	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, Update)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	CreateDefaultEntity();

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateEntity(m_entityId.c_str(), m_entityType, fw.write(entityData), "", -1, &tr);
	tr.run(m_bc);

	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, BadUpdate)
{
	TestResult tr;
	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";
	std::string badEntityId = "wakawaka";

	Json::FastWriter fw;
	m_bc->getEntityService()->updateEntity(badEntityId.c_str(), m_entityType, fw.write(entityData), "", -1, &tr);
	// TODO : put in the correct error code constant
	tr.runExpectFail(m_bc, HTTP_NOT_FOUND, 40332);
}

TEST_F(TestBCEntity, Delete)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->deleteEntity(m_entityId.c_str(), -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCEntity, GetEntity)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getEntity(m_entityId.c_str(), &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, GetSingleton)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getSingleton(m_entityType, &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TEST_F(TestBCEntity, GetSharedEntityForPlayerId)
{
	TestResult tr;
	CreateDefaultEntity();
	m_bc->getEntityService()->getSharedEntityForPlayerId(GetUser(UserA)->m_profileId, m_entityId.c_str(), &tr);
	tr.run(m_bc);
	DeleteEntity();
}
#pragma clang diagnostic pop

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TEST_F(TestBCEntity, GetSharedEntitiesForPlayerId)
{
	TestResult tr;
	CreateDefaultEntity();
	m_bc->getEntityService()->getSharedEntitiesForPlayerId(GetUser(UserA)->m_profileId, &tr);
	tr.run(m_bc);
	DeleteEntity();
}
#pragma clang diagnostic pop

TEST_F(TestBCEntity, GetEntitesByType)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->getEntitiesByType(m_entityType, &tr);
	tr.run(m_bc);
	TestBCEntity::DeleteEntity();
}

TEST_F(TestBCEntity, DeleteSingleton)
{
	TestResult tr;
	TestBCEntity::CreateDefaultEntity();
	m_bc->getEntityService()->deleteSingleton(m_entityType, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCEntity, UpdateSharedEntity)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	CreateDefaultEntity();

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateSharedEntity(m_entityId.c_str(), GetUser(UserA)->m_profileId, m_entityType, fw.write(entityData), -1, &tr);
	tr.run(m_bc);

	DeleteEntity();
}

TEST_F(TestBCEntity, UpdateSingleton)
{
	TestResult tr;
	Json::Value entityData;
	Json::FastWriter fw;

	entityData["address"] = "1309a Carling Ave, Ottawa ON";
	m_bc->getEntityService()->updateSingleton(m_entityType, fw.write(entityData), "", -1, &tr);
	if (tr.run(m_bc))
	{
		m_entityId = tr.m_response["data"]["entityId"].asString();
		ASSERT_NE("", m_entityId);
	}

	DeleteEntity(m_entityId);
}

TEST_F(TestBCEntity, GetList)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value whereJson;
	whereJson["entityType"] = m_entityType;

	m_bc->getEntityService()->getList(fw.write(whereJson), "", 100, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetSharedEntitiesListForPlayerId)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value whereJson;
	whereJson["entityType"] = m_entityType;

	m_bc->getEntityService()->getSharedEntitiesListForPlayerId(
		GetUser(UserA)->m_profileId,
		fw.write(whereJson), "", 100, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetListCount)
{
	GenerateDefaultEntites(2);
	TestResult tr;

	Json::FastWriter fw;
	Json::Value searchType;
	searchType["entityType"] = m_entityType;
	std::string searchTypeStr = fw.write(searchType);

	m_bc->getEntityService()->getListCount(searchTypeStr, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetPage)
{
	GenerateDefaultEntites(20);

	Json::Value context;
	Json::FastWriter fw;

	context["pagination"]["rowsPerPage"] = 12;
	context["pagination"]["pageNumber"] = 1;
	context["searchCriteria"]["entityType"] = m_entityType;

	TestResult tr;
	m_bc->getEntityService()->getPage(fw.write(context).c_str(), &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, GetPageOffset)
{
	GenerateDefaultEntites(20);

	Json::Value context;
	Json::FastWriter fw;

	context["pagination"]["rowsPerPage"] = 12;
	context["pagination"]["pageNumber"] = 1;
	context["searchCriteria"]["entityType"] = m_entityType;

	TestResult tr;
	m_bc->getEntityService()->getPage(fw.write(context).c_str(), &tr);
	tr.run(m_bc);

	std::string context_str = tr.m_response["data"]["context"].asString();

	tr.reset();
	m_bc->getEntityService()->getPageOffset(context_str.c_str(), 1, &tr);
	tr.run(m_bc);

	DeleteAllDefaultEntities();
}

TEST_F(TestBCEntity, IncrementUserEntityData)
{
	TestResult tr;
	Json::Value entityData;
	entityData["test"] = 1233;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc)) entityId = tr.m_response["data"]["entityId"].asString();

	m_bc->getEntityService()->incrementUserEntityData(entityId.c_str(), fw.write(entityData), &tr);
	tr.run(m_bc);

	DeleteEntity(entityId);
}

TEST_F(TestBCEntity, IncrementSharedUserEntityData)
{
	TestResult tr;
	Json::Value entityData;
	entityData["test"] = 1233;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), "", &tr);
	if (tr.run(m_bc)) entityId = tr.m_response["data"]["entityId"].asString();

	m_bc->getEntityService()->incrementSharedUserEntityData(entityId.c_str(), GetUser(UserA)->m_profileId, fw.write(entityData), &tr);
	tr.run(m_bc);

	DeleteEntity(entityId);
}

void TestBCEntity::CreateDefaultEntity()
{
	TestResult tr;
	Json::Value entityData;
	entityData["address"] = "1309 Carling Ave";
	Json::Value entityAcl;
	entityAcl["other"] = 2;

	std::string entityId;

	Json::FastWriter fw;
	m_bc->getEntityService()->createEntity(m_entityType, fw.write(entityData), fw.write(entityAcl), &tr);
	if (tr.run(m_bc))
	{
		m_entityId = tr.m_response["data"]["entityId"].asString();
	}
}

void TestBCEntity::DeleteEntity(std::string entityId)
{
	if (entityId.length() <= 0) entityId = m_entityId;
	TestResult tr;
	m_bc->getEntityService()->deleteEntity(entityId.c_str(), -1, &tr);
	tr.run(m_bc);
}

void TestBCEntity::GenerateDefaultEntites(int numToGenerate)
{
	TestResult tr;

	Json::FastWriter fw;
	Json::Value searchType;
	searchType["entityType"] = m_entityType;
	std::string searchTypeStr = fw.write(searchType);

	for (int i = 0; i < numToGenerate; i++) {
		CreateDefaultEntity();
	}
}

void TestBCEntity::DeleteAllDefaultEntities()
{
	TestResult tr;
	m_bc->getEntityService()->getEntitiesByType(m_entityType, &tr);
	if (tr.run(m_bc))
	{
		Json::Value entityArray = tr.m_response["data"]["entities"];

		/* for some reason, marmalade goes past entityArray.end() so we do this via indices
		Json::Value::iterator it;
		for (it = entityArray.begin(); it !=entityArray.end(); ++it)
		{
		Json::Value key = it.key(); // why get this?
		Json::Value value = (*it);

		DeleteEntity(value["entityId"].asString());
		}
		*/

		for (int i = 0, isize = entityArray.size(); i < isize; ++i)
		{
			Json::Value value = entityArray[i];
			DeleteEntity(value["entityId"].asString());
		}
		m_entityId = tr.m_response["data"]["entityId"].asString();
	}
}

/*
 TEST_F(TestBCTime, LargePacket)
 {
 TestResult tr;

 std::vector<int> hugeTimeout;
 hugeTimeout.push_back(180);
 m_bc->setPacketTimeouts(hugeTimeout);

 Json::Value entityData;
 int mbs = 1;
 for (int i = 0; i < mbs; ++i)
 {
 std::ostringstream oss;
 oss << i;
 std::string key = oss.str();
 oss.clear();
 for (int j = 0; j < (1024/8)*1024; ++j)
 {
 oss << "01234567";
 }
 std::string data = oss.str();
 entityData[key] = data;
 }
 Json::FastWriter fw;
 m_bc->getEntityService()->createEntity("largepacket", fw.write(entityData), "", &tr);
 if (tr.run(m_bc))
 {
 // m_entityId = tr.m_response["data"]["entityId"].asString();
 // ASSERT_NE("", m_entityId);
 }

 m_bc->setPacketTimeoutsToDefault();
 }
 */

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

// Includes needed for tests to build (since they don't include the pch).
#include <functional>
#include <vector>
#include <cmath>
#include <memory>

namespace choreograph
{

/// Define our Time type here so it's easier to change out if needed.
/// Float loses precision pretty quickly, but is fast and doesn't take up much space.
/// Double works nicely when adding together lots of little bits or if you need long sequences.
using Time = float;

template<typename T>
class Sequence;

///
/// A Phrase of motion.
/// Virtual base class with concept of value and implementation of time.
///
template<typename T>
class Phrase
{
public:
  Phrase() = default;

  Phrase( Time duration ):
    _duration( duration )
  {}

  virtual ~Phrase() = default;

  /// Override to provide value at requested time.
  /// Returns the interpolated value at the given time.
  virtual T getValue( Time atTime ) const = 0;

  /// Override to provide value at start (and before).
  virtual T getStartValue() const = 0;

  /// Override to provide value at end (and beyond).
  virtual T getEndValue() const = 0;

  /// Override to provide a copy of the derived Phrase. Needed for phrases to be copy-composable.
  virtual std::unique_ptr<Phrase<T>> clone() const = 0;

  /// Returns the Phrase value at \a time, looping past the end from inflection point to the end.
  /// Relies on the subclass implementation of getValue( t ).
  T getValueWrapped( Time time, Time inflectionPoint = 0.0f ) const { return getValue( wrapTime( time, inflectionPoint ) ); }

  /// Returns normalized time if t is in range [start_time, end_time].
  inline Time normalizeTime( Time t ) const { return t / _duration; }
  /// Returns the duration of this source.
  inline Time getDuration() const { return _duration; }

  /// Wrap \a time around \a inflectionPoint in the Sequence.
  Time wrapTime( Time time, Time inflectionPoint = 0.0f ) const
  {
    if( time > getDuration() ) {
      return inflectionPoint + std::fmodf( time, getDuration() - inflectionPoint );
    }
    else {
      return time;
    }
  }

private:
  // Duration is a generally immutable property of Phrases.
  // To change the duration, create a new phrase and insert it in your sequence.
  // This eliminates event-routing, memory allocation, and lifetime management issues.
  Time _duration = 0;

  /// Sets the duration of this source.
  /// Generally, create a new source with the duration you want and use that.
  inline void setDuration( Time duration ) { _duration = duration; }

  // Sequences can change duration, and can update their component Phrases
  friend class Sequence<T>;
};

template<typename T>
using PhraseRef = std::shared_ptr<Phrase<T>>;

template<typename T>
using PhraseUniqueRef = std::unique_ptr<Phrase<T>>;

} // namespace choreograph
<commit_msg>No more friending. const duration.<commit_after>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

// Includes needed for tests to build (since they don't include the pch).
#include <functional>
#include <vector>
#include <cmath>
#include <memory>

namespace choreograph
{

/// Define our Time type here so it's easier to change out if needed.
/// Float loses precision pretty quickly, but is fast and doesn't take up much space.
/// Double works nicely when adding together lots of little bits or if you need long sequences.
using Time = float;

template<typename T>
class Sequence;

///
/// A Phrase of motion.
/// Virtual base class with concept of value and implementation of time.
///
template<typename T>
class Phrase
{
public:
  Phrase( Time duration ):
    _duration( duration )
  {}

  virtual ~Phrase() = default;

  /// Override to provide value at requested time.
  /// Returns the interpolated value at the given time.
  virtual T getValue( Time atTime ) const = 0;

  /// Override to provide value at start (and before).
  virtual T getStartValue() const = 0;

  /// Override to provide value at end (and beyond).
  virtual T getEndValue() const = 0;

  /// Override to provide a copy of the derived Phrase. Needed for phrases to be copy-composable.
  virtual std::unique_ptr<Phrase<T>> clone() const = 0;

  /// Returns the Phrase value at \a time, looping past the end from inflection point to the end.
  /// Relies on the subclass implementation of getValue( t ).
  T getValueWrapped( Time time, Time inflectionPoint = 0.0f ) const { return getValue( wrapTime( time, inflectionPoint ) ); }

  /// Returns normalized time if t is in range [start_time, end_time].
  inline Time normalizeTime( Time t ) const { return t / _duration; }
  /// Returns the duration of this source.
  inline Time getDuration() const { return _duration; }

  /// Wrap \a time around \a inflectionPoint in the Sequence.
  Time wrapTime( Time time, Time inflectionPoint = 0.0f ) const
  {
    if( time > getDuration() ) {
      return inflectionPoint + std::fmodf( time, getDuration() - inflectionPoint );
    }
    else {
      return time;
    }
  }

private:
  // To change the duration, create a new phrase and insert it in your sequence.
  const Time _duration = 0;
};

template<typename T>
using PhraseRef = std::shared_ptr<Phrase<T>>;

template<typename T>
using PhraseUniqueRef = std::unique_ptr<Phrase<T>>;

} // namespace choreograph
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstdlib>
#include <cmath>

#include "sim/param.hh"
#include "base/random.hh"
#include "base/trace.hh"

using namespace std;

class RandomContext : public ParamContext
{
  public:
    RandomContext(const string &_iniSection)
        : ::ParamContext(_iniSection) {}
    ~RandomContext() {}

    void checkParams();
};

RandomContext paramContext("random");

Param<unsigned>
seed(&paramContext, "seed", "seed to random number generator", 1);

void
RandomContext::checkParams()
{
    ::srand48(seed);
}

long
getLong()
{
    return mrand48();
}

int64_t
getUniform(int64_t maxmin)
{
    double r;
    r = (drand48() - 0.500) * 2 * maxmin;
    DPRINTFN("getUniform %f\n", r);
    return (int64_t)round(r);
}

uint64_t
getUniformPos(uint64_t max)
{
    double r;
    r = drand48() * 2 * max;
    return (uint64_t)round(r);
}

// idea for generating a double from erand48
double
getDouble()
{
    union {
        uint32_t _long[2];
        uint16_t _short[4];
    };

    _long[0] = mrand48();
    _long[1] = mrand48();

    return ldexp((double) _short[0], -48) +
        ldexp((double) _short[1], -32) +
        ldexp((double) _short[2], -16);
}
<commit_msg>I left a printf in on accident.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstdlib>
#include <cmath>

#include "sim/param.hh"
#include "base/random.hh"
#include "base/trace.hh"

using namespace std;

class RandomContext : public ParamContext
{
  public:
    RandomContext(const string &_iniSection)
        : ::ParamContext(_iniSection) {}
    ~RandomContext() {}

    void checkParams();
};

RandomContext paramContext("random");

Param<unsigned>
seed(&paramContext, "seed", "seed to random number generator", 1);

void
RandomContext::checkParams()
{
    ::srand48(seed);
}

long
getLong()
{
    return mrand48();
}

int64_t
getUniform(int64_t maxmin)
{
    double r;
    r = (drand48() - 0.500) * 2 * maxmin;
    return (int64_t)round(r);
}

uint64_t
getUniformPos(uint64_t max)
{
    double r;
    r = drand48() * 2 * max;
    return (uint64_t)round(r);
}

// idea for generating a double from erand48
double
getDouble()
{
    union {
        uint32_t _long[2];
        uint16_t _short[4];
    };

    _long[0] = mrand48();
    _long[1] = mrand48();

    return ldexp((double) _short[0], -48) +
        ldexp((double) _short[1], -32) +
        ldexp((double) _short[2], -16);
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

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

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

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

#include "cinder/audio/Input.h"
#if defined( CINDER_COCOA )
	#include "cinder/audio/InputImplAudioUnit.h"
	typedef cinder::audio::InputImplAudioUnit	InputPlatformImpl;
#endif

namespace cinder { namespace audio {

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Input

Input::Input()
{
	mImpl = std::shared_ptr<InputImpl>( new InputPlatformImpl( InputDeviceRef() ) );
}

Input::Input( InputDeviceRef aDevice )
{
	mImpl = std::shared_ptr<InputImpl>( new InputPlatformImpl( aDevice ) );
}

const std::vector<InputDeviceRef>&	Input::getDevices( bool forceRefresh )
{
	return InputPlatformImpl::getDevices( forceRefresh );
}

InputDeviceRef Input::getDefaultDevice()
{
	return InputPlatformImpl::getDefaultDevice();
}

InputDeviceRef Input::findDeviceByName( const std::string &name )
{
	return InputDeviceRef();
}

InputDeviceRef Input::findDeviceByNameContains( const std::string &nameFragment )
{
	return InputDeviceRef();
}

}} //namespace<commit_msg>Implement audio Input::findDeviceByName and findDeviceByNameContains.<commit_after>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

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

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

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

#include "cinder/audio/Input.h"
#if defined( CINDER_COCOA )
	#include "cinder/audio/InputImplAudioUnit.h"
	typedef cinder::audio::InputImplAudioUnit	InputPlatformImpl;
#endif

namespace cinder { namespace audio {

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Input

Input::Input()
{
	mImpl = std::shared_ptr<InputImpl>( new InputPlatformImpl( InputDeviceRef() ) );
}

Input::Input( InputDeviceRef aDevice )
{
	mImpl = std::shared_ptr<InputImpl>( new InputPlatformImpl( aDevice ) );
}

const std::vector<InputDeviceRef>&	Input::getDevices( bool forceRefresh )
{
	return InputPlatformImpl::getDevices( forceRefresh );
}

InputDeviceRef Input::getDefaultDevice()
{
	return InputPlatformImpl::getDefaultDevice();
}

InputDeviceRef Input::findDeviceByName( const std::string &name )
{
	const std::vector<InputDeviceRef>& devices = getDevices();
	for (size_t i = 0; i < devices.size(); ++i) {
		if (devices[i]->getName() == name)
			return devices[i];
	}
	return InputDeviceRef();
}

InputDeviceRef Input::findDeviceByNameContains( const std::string &nameFragment )
{
	const std::vector<InputDeviceRef>& devices = getDevices();
	for (size_t i = 0; i < devices.size(); ++i) {
		if (devices[i]->getName().find(nameFragment) != std::string::npos)
			return devices[i];
	}
	return InputDeviceRef();
}

}} //namespace
<|endoftext|>