<ClInclude Include="filesystem\polling_filesystem_monitor.h" />\r
<ClInclude Include="gl\gl_check.h" />\r
<ClInclude Include="log\log.h" />\r
+ <ClInclude Include="memory\byte_order.h" />\r
<ClInclude Include="memory\memclr.h" />\r
<ClInclude Include="memory\memcpy.h" />\r
<ClInclude Include="memory\memshfl.h" />\r
<ClInclude Include="utility\iterator.h">\r
<Filter>source\utility</Filter>\r
</ClInclude>\r
+ <ClInclude Include="memory\byte_order.h">\r
+ <Filter>source\memory</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include <intrin.h>
+
+namespace caspar {
+
+template<typename T>
+inline T swap_byte_order(T value)
+{
+ T result;
+
+ swap_byte_order<sizeof(T)>(
+ reinterpret_cast<const char*>(&value),
+ reinterpret_cast<char*>(&result));
+
+ return result;
+}
+
+template<size_t num_bytes>
+inline void swap_byte_order(const char* src, char* dest)
+{
+ for (int i = 0, j = num_bytes - 1; i != num_bytes; ++i, --j)
+ dest[i] = src[j];
+}
+
+template<>
+inline void swap_byte_order<sizeof(unsigned short)>(const char* src, char* dest)
+{
+ auto result = reinterpret_cast<unsigned short*>(dest);
+ auto value = reinterpret_cast<const unsigned short*>(src);
+ *result = _byteswap_ushort(*value);
+}
+
+template<>
+inline void swap_byte_order<sizeof(unsigned long)>(const char* src, char* dest)
+{
+ auto result = reinterpret_cast<unsigned long*>(dest);
+ auto value = reinterpret_cast<const unsigned long*>(src);
+ *result = _byteswap_ulong(*value);
+}
+
+template<>
+inline void swap_byte_order<sizeof(unsigned __int64)>(const char* src, char* dest)
+{
+ auto result = reinterpret_cast<unsigned __int64*>(dest);
+ auto value = reinterpret_cast<const unsigned __int64*>(src);
+ *result = _byteswap_uint64(*value);
+}
+
+}
#ifndef OSC_HOSTENDIANNESS_H
#define OSC_HOSTENDIANNESS_H
-//#define OSC_HOST_BIG_ENDIAN 1
-
-//*
-// Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined
-//
-// If you know a way to enhance the detection below for Linux and/or MacOSX
-// please let me know! I've tried a few things which don't work.
-//*/
-//
-//#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)
-//
+#define OSC_HOST_LITTLE_ENDIAN 1
+
+/*
+ Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined
+
+ If you know a way to enhance the detection below for Linux and/or MacOSX
+ please let me know! I've tried a few things which don't work.
+*/
+
+#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)
+
// you can define one of the above symbols from the command line
// then you don't have to edit this file.
-//
-//#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)
-//
+
+#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)
+
// assume that __WIN32__ is only defined on little endian systems
-//
-//#define OSC_HOST_LITTLE_ENDIAN 1
-//#undef OSC_HOST_BIG_ENDIAN
-//
-//#elif defined(__APPLE__)
-//
-//#if defined(__LITTLE_ENDIAN__)
-//
-//#define OSC_HOST_LITTLE_ENDIAN 1
-//#undef OSC_HOST_BIG_ENDIAN
-//
-//#elif defined(__BIG_ENDIAN__)
-//
-//#define OSC_HOST_BIG_ENDIAN 1
-//#undef OSC_HOST_LITTLE_ENDIAN
-//
-//#endif
-//
-//#endif
-//
-//#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)
-//
-//#error please edit OSCHostEndianness.h to configure endianness
-//
-//#endif
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif defined(__APPLE__)
+
+#if defined(__LITTLE_ENDIAN__)
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif defined(__BIG_ENDIAN__)
+
+#define OSC_HOST_BIG_ENDIAN 1
+#undef OSC_HOST_LITTLE_ENDIAN
+
+#endif
+
+#endif
+
+#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)
+
+#error please edit OSCHostEndianness.h to configure endianness
+
+#endif
#endif /* OSC_HOSTENDIANNESS_H */
#include <stdlib.h>
#include <assert.h>
+#include <common/memory/byte_order.h>
+
#if defined(__WIN32__) || defined(WIN32)
#include <malloc.h> // for alloca
#endif
static void FromInt32( char *p, int32 x )
{
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<int32*>(p) = caspar::swap_byte_order(x);
+ /*union{
osc::int32 i;
char c[4];
} u;
p[3] = u.c[0];
p[2] = u.c[1];
p[1] = u.c[2];
- p[0] = u.c[3];
+ p[0] = u.c[3];*/
#else
*reinterpret_cast<int32*>(p) = x;
#endif
static void FromUInt32( char *p, uint32 x )
{
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<uint32*>(p) = caspar::swap_byte_order(x);
+ /*union{
osc::uint32 i;
char c[4];
} u;
p[3] = u.c[0];
p[2] = u.c[1];
p[1] = u.c[2];
- p[0] = u.c[3];
+ p[0] = u.c[3];*/
#else
*reinterpret_cast<uint32*>(p) = x;
#endif
static void FromInt64( char *p, int64 x )
{
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<int64*>(p) = caspar::swap_byte_order(x);
+ /*union{
osc::int64 i;
char c[8];
} u;
p[3] = u.c[4];
p[2] = u.c[5];
p[1] = u.c[6];
- p[0] = u.c[7];
+ p[0] = u.c[7];*/
#else
*reinterpret_cast<int64*>(p) = x;
#endif
static void FromUInt64( char *p, uint64 x )
{
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<uint64*>(p) = caspar::swap_byte_order(x);
+ /*union{
osc::uint64 i;
char c[8];
} u;
p[3] = u.c[4];
p[2] = u.c[5];
p[1] = u.c[6];
- p[0] = u.c[7];
+ p[0] = u.c[7];*/
#else
*reinterpret_cast<uint64*>(p) = x;
#endif
*(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<float*>(argumentCurrent_) = caspar::swap_byte_order(rhs);
+ /*union{
float f;
char c[4];
} u;
argumentCurrent_[3] = u.c[0];
argumentCurrent_[2] = u.c[1];
argumentCurrent_[1] = u.c[2];
- argumentCurrent_[0] = u.c[3];
+ argumentCurrent_[0] = u.c[3];*/
#else
*reinterpret_cast<float*>(argumentCurrent_) = rhs;
#endif
*(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
#ifdef OSC_HOST_LITTLE_ENDIAN
- union{
+ *reinterpret_cast<double*>(argumentCurrent_) = caspar::swap_byte_order(rhs);
+ /*union{
double f;
char c[8];
} u;
argumentCurrent_[3] = u.c[4];
argumentCurrent_[2] = u.c[5];
argumentCurrent_[1] = u.c[6];
- argumentCurrent_[0] = u.c[7];
+ argumentCurrent_[0] = u.c[7];*/
#else
*reinterpret_cast<double*>(argumentCurrent_) = rhs;
#endif
#include <core/video_channel.h>\r
#include <core/producer/stage.h>\r
#include <core/consumer/output.h>\r
+#include <core/consumer/synchronizing/synchronizing_consumer.h>\r
#include <core/thumbnail_generator.h>\r
\r
#include <modules/bluefish/bluefish.h>\r
\r
channels_.back()->monitor_output().link_target(&monitor_subject_);\r
\r
- BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child(L"consumers"))\r
- {\r
- try\r
- {\r
- auto name = xml_consumer.first;\r
- if(name == L"screen")\r
- channels_.back()->output()->add(ogl::create_consumer(xml_consumer.second)); \r
- else if(name == L"bluefish") \r
- channels_.back()->output()->add(bluefish::create_consumer(xml_consumer.second)); \r
- else if(name == L"decklink") \r
- channels_.back()->output()->add(decklink::create_consumer(xml_consumer.second)); \r
- else if(name == L"file") \r
- channels_.back()->output()->add(ffmpeg::create_consumer(xml_consumer.second)); \r
- else if(name == L"system-audio")\r
- channels_.back()->output()->add(oal::create_consumer()); \r
- else if(name != L"<xmlcomment>")\r
- CASPAR_LOG(warning) << "Invalid consumer: " << widen(name); \r
- }\r
- catch(...)\r
+ create_consumers(\r
+ xml_channel.second.get_child(L"consumers"),\r
+ [&] (const safe_ptr<core::frame_consumer>& consumer)\r
{\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- }\r
- } \r
+ channels_.back()->output()->add(consumer);\r
+ });\r
+\r
+ // Add all consumers before starting channel.\r
+ channels_.back()->start_channel();\r
}\r
\r
// Dummy diagnostics channel\r
if(env::properties().get(L"configuration.channel-grid", false))\r
+ {\r
channels_.push_back(make_safe<video_channel>(channels_.size()+1, core::video_format_desc::get(core::video_format::x576p2500), ogl_, default_channel_layout_repository().get_by_name(L"STEREO")));\r
+ channels_.back()->start_channel();\r
+ }\r
+ }\r
+\r
+ template<typename Base>\r
+ std::vector<safe_ptr<Base>> create_consumers(const boost::property_tree::wptree& pt)\r
+ {\r
+ std::vector<safe_ptr<Base>> consumers;\r
+\r
+ create_consumers(pt, [&] (const safe_ptr<core::frame_consumer>& consumer)\r
+ {\r
+ consumers.push_back(dynamic_pointer_cast<Base>(consumer));\r
+ });\r
+\r
+ return consumers;\r
+ }\r
+\r
+ template<class Func>\r
+ void create_consumers(const boost::property_tree::wptree& pt, const Func& on_consumer)\r
+ {\r
+ BOOST_FOREACH(auto& xml_consumer, pt)\r
+ {\r
+ try\r
+ {\r
+ auto name = xml_consumer.first;\r
+ if (name == L"screen")\r
+ on_consumer(ogl::create_consumer(xml_consumer.second));\r
+ else if (name == L"bluefish") \r
+ on_consumer(bluefish::create_consumer(xml_consumer.second)); \r
+ else if (name == L"decklink") \r
+ on_consumer(decklink::create_consumer(xml_consumer.second)); \r
+ else if (name == L"file") \r
+ on_consumer(ffmpeg::create_consumer(xml_consumer.second)); \r
+ else if (name == L"system-audio")\r
+ on_consumer(oal::create_consumer());\r
+ else if (name == L"synchronizing")\r
+ on_consumer(make_safe<core::synchronizing_consumer>(create_consumers<core::synchronizable_consumer>(xml_consumer.second)));\r
+ else if (name != L"<xmlcomment>")\r
+ CASPAR_LOG(warning) << "Invalid consumer: " << widen(name); \r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ }\r
}\r
\r
void setup_controllers(const boost::property_tree::wptree& pt)\r