]> git.sesse.net Git - casparcg/commitdiff
Subtree merge of old SVN "dependencies" folder into the "master" git branch. You...
authorTK3 <tomkaltz@gmail.com>
Sun, 24 Mar 2013 14:48:05 +0000 (10:48 -0400)
committerTK3 <tomkaltz@gmail.com>
Sun, 24 Mar 2013 23:48:43 +0000 (19:48 -0400)
781 files changed:
CHANGES.txt [new file with mode: 0644]
LICENSE.txt [moved from ffmpeg 0.8/licenses/ffmpeg.txt with 100% similarity]
README.txt [new file with mode: 0644]
casparcg.sln [new file with mode: 0644]
common/common.vcxproj [new file with mode: 0644]
common/common.vcxproj.filters [new file with mode: 0644]
common/common.vcxproj.user [new file with mode: 0644]
common/compiler/vs/disable_silly_warnings.h [new file with mode: 0644]
common/concurrency/com_context.h [new file with mode: 0644]
common/concurrency/executor.h [new file with mode: 0644]
common/concurrency/future_util.h [new file with mode: 0644]
common/concurrency/lock.h [new file with mode: 0644]
common/concurrency/target.h [new file with mode: 0644]
common/diagnostics/graph.cpp [new file with mode: 0644]
common/diagnostics/graph.h [new file with mode: 0644]
common/env.cpp [new file with mode: 0644]
common/env.h [new file with mode: 0644]
common/exception/exceptions.h [new file with mode: 0644]
common/exception/win32_exception.cpp [new file with mode: 0644]
common/exception/win32_exception.h [new file with mode: 0644]
common/filesystem/filesystem_monitor.h [new file with mode: 0644]
common/filesystem/polling_filesystem_monitor.cpp [new file with mode: 0644]
common/filesystem/polling_filesystem_monitor.h [new file with mode: 0644]
common/gl/gl_check.cpp [new file with mode: 0644]
common/gl/gl_check.h [new file with mode: 0644]
common/log/log.cpp [new file with mode: 0644]
common/log/log.h [new file with mode: 0644]
common/memory/memclr.h [new file with mode: 0644]
common/memory/memcpy.h [new file with mode: 0644]
common/memory/memshfl.h [new file with mode: 0644]
common/memory/page_locked_allocator.h [new file with mode: 0644]
common/memory/safe_ptr.h [new file with mode: 0644]
common/os/windows/current_version.h [new file with mode: 0644]
common/os/windows/system_info.h [new file with mode: 0644]
common/printable.h [new file with mode: 0644]
common/stdafx.cpp [new file with mode: 0644]
common/stdafx.h [new file with mode: 0644]
common/utility/assert.h [new file with mode: 0644]
common/utility/move_on_copy.h [new file with mode: 0644]
common/utility/param.h [new file with mode: 0644]
common/utility/string.cpp [new file with mode: 0644]
common/utility/string.h [new file with mode: 0644]
common/utility/timer.h [new file with mode: 0644]
common/utility/tweener.cpp [new file with mode: 0644]
common/utility/tweener.h [new file with mode: 0644]
common/utility/utf8conv.h [new file with mode: 0644]
common/utility/utf8conv_inl.h [new file with mode: 0644]
core/StdAfx.cpp [new file with mode: 0644]
core/StdAfx.h [new file with mode: 0644]
core/consumer/frame/read_frame.h [new file with mode: 0644]
core/consumer/frame_consumer.cpp [new file with mode: 0644]
core/consumer/frame_consumer.h [new file with mode: 0644]
core/consumer/output.cpp [new file with mode: 0644]
core/consumer/output.h [new file with mode: 0644]
core/core.vcxproj [new file with mode: 0644]
core/core.vcxproj.filters [new file with mode: 0644]
core/mixer/audio/audio_mixer.cpp [new file with mode: 0644]
core/mixer/audio/audio_mixer.h [new file with mode: 0644]
core/mixer/audio/audio_util.h [new file with mode: 0644]
core/mixer/gpu/device_buffer.cpp [new file with mode: 0644]
core/mixer/gpu/device_buffer.h [new file with mode: 0644]
core/mixer/gpu/fence.cpp [new file with mode: 0644]
core/mixer/gpu/fence.h [new file with mode: 0644]
core/mixer/gpu/host_buffer.cpp [new file with mode: 0644]
core/mixer/gpu/host_buffer.h [new file with mode: 0644]
core/mixer/gpu/ogl_device.cpp [new file with mode: 0644]
core/mixer/gpu/ogl_device.h [new file with mode: 0644]
core/mixer/gpu/shader.cpp [new file with mode: 0644]
core/mixer/gpu/shader.h [new file with mode: 0644]
core/mixer/image/blend_modes.cpp [new file with mode: 0644]
core/mixer/image/blend_modes.h [new file with mode: 0644]
core/mixer/image/image_kernel.cpp [new file with mode: 0644]
core/mixer/image/image_kernel.h [new file with mode: 0644]
core/mixer/image/image_mixer.cpp [new file with mode: 0644]
core/mixer/image/image_mixer.h [new file with mode: 0644]
core/mixer/image/shader/blending_glsl.h [new file with mode: 0644]
core/mixer/image/shader/image_shader.cpp [new file with mode: 0644]
core/mixer/image/shader/image_shader.h [new file with mode: 0644]
core/mixer/mixer.cpp [new file with mode: 0644]
core/mixer/mixer.h [new file with mode: 0644]
core/mixer/read_frame.cpp [new file with mode: 0644]
core/mixer/read_frame.h [new file with mode: 0644]
core/mixer/write_frame.cpp [new file with mode: 0644]
core/mixer/write_frame.h [new file with mode: 0644]
core/producer/channel/channel_producer.cpp [new file with mode: 0644]
core/producer/channel/channel_producer.h [new file with mode: 0644]
core/producer/color/color_producer.cpp [new file with mode: 0644]
core/producer/color/color_producer.h [new file with mode: 0644]
core/producer/frame/basic_frame.cpp [new file with mode: 0644]
core/producer/frame/basic_frame.h [new file with mode: 0644]
core/producer/frame/frame_factory.h [new file with mode: 0644]
core/producer/frame/frame_transform.cpp [new file with mode: 0644]
core/producer/frame/frame_transform.h [new file with mode: 0644]
core/producer/frame/frame_visitor.h [new file with mode: 0644]
core/producer/frame/pixel_format.h [new file with mode: 0644]
core/producer/frame_producer.cpp [new file with mode: 0644]
core/producer/frame_producer.h [new file with mode: 0644]
core/producer/layer.cpp [new file with mode: 0644]
core/producer/layer.h [new file with mode: 0644]
core/producer/playlist/playlist_producer.cpp [new file with mode: 0644]
core/producer/playlist/playlist_producer.h [new file with mode: 0644]
core/producer/separated/separated_producer.cpp [new file with mode: 0644]
core/producer/separated/separated_producer.h [new file with mode: 0644]
core/producer/stage.cpp [new file with mode: 0644]
core/producer/stage.h [new file with mode: 0644]
core/producer/transition/transition_producer.cpp [new file with mode: 0644]
core/producer/transition/transition_producer.h [new file with mode: 0644]
core/thumbnail_generator.cpp [new file with mode: 0644]
core/thumbnail_generator.h [new file with mode: 0644]
core/video_channel.cpp [new file with mode: 0644]
core/video_channel.h [new file with mode: 0644]
core/video_format.cpp [new file with mode: 0644]
core/video_format.h [new file with mode: 0644]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueC_Api.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueC_Api.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueDriver_p.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueDriver_p.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueHANC.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueHANC.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueHancUtils.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueHancUtils.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueTypes.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueTypes.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueVelvet.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueVelvet.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueVelvet4.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueVelvet4.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Inc/BlueVelvet_c.h [moved from BluefishSDK_V5_10_0_42/Inc/BlueVelvet_c.h with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueFishFilters.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueFishFilters.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueFishFilters.tlb [moved from BluefishSDK_V5_10_0_42/Lib/BlueFishFilters.tlb with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueFishFilters64.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueFishFilters64.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueFishFilters64.tlb [moved from BluefishSDK_V5_10_0_42/Lib/BlueFishFilters64.tlb with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueHancUtils.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueHancUtils.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueHancUtils64.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueHancUtils64.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueHancUtils64_d.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueHancUtils64_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueHancUtils_d.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueHancUtils_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvet3.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvet3.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvet3_d.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvet3_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvet64.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvet64.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvet64_d.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvet64_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvetCom.lib [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvetCom.lib with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvetCom.tlb [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvetCom.tlb with 100% similarity]
dependencies/BluefishSDK_V5_10_0_42/Lib/BlueVelvetConstant.tlb [moved from BluefishSDK_V5_10_0_42/Lib/BlueVelvetConstant.tlb with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueC_Api.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueC_Api.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueHancUtils.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueHancUtils.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueLUTCreation.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueLUTCreation.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueTimer.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueTimer.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueTypes.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueTypes.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueVelvet.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueVelvet.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueVelvet4.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueVelvet4.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BlueVelvet_c.h [moved from BluefishSDK_V5_8_0_31/Inc/BlueVelvet_c.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/BluefishApi.h [moved from BluefishSDK_V5_8_0_31/Inc/BluefishApi.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/bluedriver_p.h [moved from BluefishSDK_V5_8_0_31/Inc/bluedriver_p.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Inc/bluehanc.h [moved from BluefishSDK_V5_8_0_31/Inc/bluehanc.h with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueFishFilters.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueFishFilters.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueHancUtils.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueHancUtils.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueHancUtils64.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueHancUtils64.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueHancUtils64_d.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueHancUtils64_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueHancUtils_d.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueHancUtils_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueTimer.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueTimer.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvet3.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvet3.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvet3_d.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvet3_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvet64.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvet64.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvet64_d.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvet64_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvetCom.lib [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvetCom.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvetCom.tlb [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvetCom.tlb with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BlueVelvetConstant.tlb [moved from BluefishSDK_V5_8_0_31/Lib/BlueVelvetConstant.tlb with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BluefishApiStatic.lib [moved from BluefishSDK_V5_8_0_31/Lib/BluefishApiStatic.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BluefishApi_d.lib [moved from BluefishSDK_V5_8_0_31/Lib/BluefishApi_d.lib with 100% similarity]
dependencies/BluefishSDK_V5_8_0_31/Lib/BluefishFilters.tlb [moved from BluefishSDK_V5_8_0_31/Lib/BluefishFilters.tlb with 100% similarity]
dependencies/FreeImage/Dist/FreeImage.dll [moved from FreeImage/Dist/FreeImage.dll with 100% similarity]
dependencies/FreeImage/Dist/FreeImage.h [moved from FreeImage/Dist/FreeImage.h with 100% similarity]
dependencies/FreeImage/Dist/FreeImage.lib [moved from FreeImage/Dist/FreeImage.lib with 100% similarity]
dependencies/FreeImage/Dist/delete.me [moved from FreeImage/Dist/delete.me with 100% similarity]
dependencies/FreeImage/FreeImage3131.pdf [moved from FreeImage/FreeImage3131.pdf with 100% similarity]
dependencies/FreeImage/README.minGW [moved from FreeImage/README.minGW with 100% similarity]
dependencies/FreeImage/license-fi.txt [moved from FreeImage/license-fi.txt with 100% similarity]
dependencies/FreeImage/license-gpl.txt [moved from FreeImage/license-gpl.txt with 100% similarity]
dependencies/SFML-1.6/extlibs/bin/libsndfile-1.dll [moved from SFML-1.6/extlibs/bin/libsndfile-1.dll with 100% similarity]
dependencies/SFML-1.6/extlibs/bin/openal32.dll [moved from SFML-1.6/extlibs/bin/openal32.dll with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/AL/al.h [moved from SFML-1.6/extlibs/headers/AL/al.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/AL/alc.h [moved from SFML-1.6/extlibs/headers/AL/alc.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/AL/alext.h [moved from SFML-1.6/extlibs/headers/AL/alext.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftccache.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftccache.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftccmap.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftccmap.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftcglyph.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftcglyph.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftcimage.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftcimage.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftcmanag.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftcmanag.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftcmru.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftcmru.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/cache/ftcsbits.h [moved from SFML-1.6/extlibs/headers/freetype/cache/ftcsbits.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/config/ftconfig.h [moved from SFML-1.6/extlibs/headers/freetype/config/ftconfig.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/config/ftheader.h [moved from SFML-1.6/extlibs/headers/freetype/config/ftheader.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/config/ftmodule.h [moved from SFML-1.6/extlibs/headers/freetype/config/ftmodule.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/config/ftoption.h [moved from SFML-1.6/extlibs/headers/freetype/config/ftoption.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/config/ftstdlib.h [moved from SFML-1.6/extlibs/headers/freetype/config/ftstdlib.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/freetype.h [moved from SFML-1.6/extlibs/headers/freetype/freetype.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ft2build.h [moved from SFML-1.6/extlibs/headers/freetype/ft2build.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftbbox.h [moved from SFML-1.6/extlibs/headers/freetype/ftbbox.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftbdf.h [moved from SFML-1.6/extlibs/headers/freetype/ftbdf.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftbitmap.h [moved from SFML-1.6/extlibs/headers/freetype/ftbitmap.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftcache.h [moved from SFML-1.6/extlibs/headers/freetype/ftcache.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftchapters.h [moved from SFML-1.6/extlibs/headers/freetype/ftchapters.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/fterrdef.h [moved from SFML-1.6/extlibs/headers/freetype/fterrdef.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/fterrors.h [moved from SFML-1.6/extlibs/headers/freetype/fterrors.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftglyph.h [moved from SFML-1.6/extlibs/headers/freetype/ftglyph.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftgzip.h [moved from SFML-1.6/extlibs/headers/freetype/ftgzip.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftimage.h [moved from SFML-1.6/extlibs/headers/freetype/ftimage.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftincrem.h [moved from SFML-1.6/extlibs/headers/freetype/ftincrem.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftlist.h [moved from SFML-1.6/extlibs/headers/freetype/ftlist.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftlzw.h [moved from SFML-1.6/extlibs/headers/freetype/ftlzw.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftmac.h [moved from SFML-1.6/extlibs/headers/freetype/ftmac.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftmm.h [moved from SFML-1.6/extlibs/headers/freetype/ftmm.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftmodapi.h [moved from SFML-1.6/extlibs/headers/freetype/ftmodapi.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftmoderr.h [moved from SFML-1.6/extlibs/headers/freetype/ftmoderr.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftotval.h [moved from SFML-1.6/extlibs/headers/freetype/ftotval.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftoutln.h [moved from SFML-1.6/extlibs/headers/freetype/ftoutln.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftpfr.h [moved from SFML-1.6/extlibs/headers/freetype/ftpfr.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftrender.h [moved from SFML-1.6/extlibs/headers/freetype/ftrender.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsizes.h [moved from SFML-1.6/extlibs/headers/freetype/ftsizes.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsnames.h [moved from SFML-1.6/extlibs/headers/freetype/ftsnames.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftstroke.h [moved from SFML-1.6/extlibs/headers/freetype/ftstroke.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsynth.h [moved from SFML-1.6/extlibs/headers/freetype/ftsynth.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsysio.h [moved from SFML-1.6/extlibs/headers/freetype/ftsysio.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsysmem.h [moved from SFML-1.6/extlibs/headers/freetype/ftsysmem.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftsystem.h [moved from SFML-1.6/extlibs/headers/freetype/ftsystem.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/fttrigon.h [moved from SFML-1.6/extlibs/headers/freetype/fttrigon.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/fttypes.h [moved from SFML-1.6/extlibs/headers/freetype/fttypes.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftwinfnt.h [moved from SFML-1.6/extlibs/headers/freetype/ftwinfnt.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ftxf86.h [moved from SFML-1.6/extlibs/headers/freetype/ftxf86.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/autohint.h [moved from SFML-1.6/extlibs/headers/freetype/internal/autohint.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftcalc.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftcalc.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftdebug.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftdebug.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftdriver.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftdriver.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftgloadr.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftgloadr.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftmemory.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftmemory.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftobjs.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftobjs.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftrfork.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftrfork.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftserv.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftserv.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftstream.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftstream.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/fttrace.h [moved from SFML-1.6/extlibs/headers/freetype/internal/fttrace.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/ftvalid.h [moved from SFML-1.6/extlibs/headers/freetype/internal/ftvalid.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/internal.h [moved from SFML-1.6/extlibs/headers/freetype/internal/internal.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/pcftypes.h [moved from SFML-1.6/extlibs/headers/freetype/internal/pcftypes.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/psaux.h [moved from SFML-1.6/extlibs/headers/freetype/internal/psaux.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/pshints.h [moved from SFML-1.6/extlibs/headers/freetype/internal/pshints.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/sfnt.h [moved from SFML-1.6/extlibs/headers/freetype/internal/sfnt.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svbdf.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svbdf.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svgldict.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svgldict.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svmm.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svmm.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svotval.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svotval.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svpfr.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svpfr.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svpostnm.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svpostnm.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svpscmap.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svpscmap.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svpsinfo.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svpsinfo.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svsfnt.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svsfnt.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svttcmap.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svttcmap.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svwinfnt.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svwinfnt.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/svxf86nm.h [moved from SFML-1.6/extlibs/headers/freetype/internal/svxf86nm.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/t1types.h [moved from SFML-1.6/extlibs/headers/freetype/internal/t1types.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/internal/tttypes.h [moved from SFML-1.6/extlibs/headers/freetype/internal/tttypes.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/t1tables.h [moved from SFML-1.6/extlibs/headers/freetype/t1tables.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ttnameid.h [moved from SFML-1.6/extlibs/headers/freetype/ttnameid.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/tttables.h [moved from SFML-1.6/extlibs/headers/freetype/tttables.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/tttags.h [moved from SFML-1.6/extlibs/headers/freetype/tttags.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/freetype/ttunpat.h [moved from SFML-1.6/extlibs/headers/freetype/ttunpat.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/ft2build.h [moved from SFML-1.6/extlibs/headers/ft2build.h with 100% similarity]
dependencies/SFML-1.6/extlibs/headers/sndfile.h [moved from SFML-1.6/extlibs/headers/sndfile.h with 100% similarity]
dependencies/SFML-1.6/extlibs/libs-vc2005/OpenAL32.lib [moved from SFML-1.6/extlibs/libs-vc2005/OpenAL32.lib with 100% similarity]
dependencies/SFML-1.6/extlibs/libs-vc2005/freetype.lib [moved from SFML-1.6/extlibs/libs-vc2005/freetype.lib with 100% similarity]
dependencies/SFML-1.6/extlibs/libs-vc2005/sndfile.lib [moved from SFML-1.6/extlibs/libs-vc2005/sndfile.lib with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio.hpp [moved from SFML-1.6/include/SFML/Audio.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/AudioResource.hpp [moved from SFML-1.6/include/SFML/Audio/AudioResource.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/Listener.hpp [moved from SFML-1.6/include/SFML/Audio/Listener.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/Music.hpp [moved from SFML-1.6/include/SFML/Audio/Music.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/Sound.hpp [moved from SFML-1.6/include/SFML/Audio/Sound.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/SoundBuffer.hpp [moved from SFML-1.6/include/SFML/Audio/SoundBuffer.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/SoundBufferRecorder.hpp [moved from SFML-1.6/include/SFML/Audio/SoundBufferRecorder.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/SoundRecorder.hpp [moved from SFML-1.6/include/SFML/Audio/SoundRecorder.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Audio/SoundStream.hpp [moved from SFML-1.6/include/SFML/Audio/SoundStream.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Config.hpp [moved from SFML-1.6/include/SFML/Config.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics.hpp [moved from SFML-1.6/include/SFML/Graphics.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Color.hpp [moved from SFML-1.6/include/SFML/Graphics/Color.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Drawable.hpp [moved from SFML-1.6/include/SFML/Graphics/Drawable.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Font.hpp [moved from SFML-1.6/include/SFML/Graphics/Font.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Glyph.hpp [moved from SFML-1.6/include/SFML/Graphics/Glyph.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Image.hpp [moved from SFML-1.6/include/SFML/Graphics/Image.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Matrix3.hpp [moved from SFML-1.6/include/SFML/Graphics/Matrix3.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Matrix3.inl [moved from SFML-1.6/include/SFML/Graphics/Matrix3.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/PostFX.hpp [moved from SFML-1.6/include/SFML/Graphics/PostFX.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Rect.hpp [moved from SFML-1.6/include/SFML/Graphics/Rect.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Rect.inl [moved from SFML-1.6/include/SFML/Graphics/Rect.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/RenderTarget.hpp [moved from SFML-1.6/include/SFML/Graphics/RenderTarget.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/RenderWindow.hpp [moved from SFML-1.6/include/SFML/Graphics/RenderWindow.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Shape.hpp [moved from SFML-1.6/include/SFML/Graphics/Shape.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/Sprite.hpp [moved from SFML-1.6/include/SFML/Graphics/Sprite.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/String.hpp [moved from SFML-1.6/include/SFML/Graphics/String.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Graphics/View.hpp [moved from SFML-1.6/include/SFML/Graphics/View.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network.hpp [moved from SFML-1.6/include/SFML/Network.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Ftp.hpp [moved from SFML-1.6/include/SFML/Network/Ftp.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Http.hpp [moved from SFML-1.6/include/SFML/Network/Http.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/IPAddress.hpp [moved from SFML-1.6/include/SFML/Network/IPAddress.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Packet.hpp [moved from SFML-1.6/include/SFML/Network/Packet.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Selector.hpp [moved from SFML-1.6/include/SFML/Network/Selector.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Selector.inl [moved from SFML-1.6/include/SFML/Network/Selector.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/SelectorBase.hpp [moved from SFML-1.6/include/SFML/Network/SelectorBase.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/SocketHelper.hpp [moved from SFML-1.6/include/SFML/Network/SocketHelper.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/SocketTCP.hpp [moved from SFML-1.6/include/SFML/Network/SocketTCP.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/SocketUDP.hpp [moved from SFML-1.6/include/SFML/Network/SocketUDP.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Sockets.hpp [moved from SFML-1.6/include/SFML/Network/Sockets.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Unix/SocketHelper.hpp [moved from SFML-1.6/include/SFML/Network/Unix/SocketHelper.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Network/Win32/SocketHelper.hpp [moved from SFML-1.6/include/SFML/Network/Win32/SocketHelper.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System.hpp [moved from SFML-1.6/include/SFML/System.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Clock.hpp [moved from SFML-1.6/include/SFML/System/Clock.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Lock.hpp [moved from SFML-1.6/include/SFML/System/Lock.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Mutex.hpp [moved from SFML-1.6/include/SFML/System/Mutex.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/NonCopyable.hpp [moved from SFML-1.6/include/SFML/System/NonCopyable.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Randomizer.hpp [moved from SFML-1.6/include/SFML/System/Randomizer.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Resource.hpp [moved from SFML-1.6/include/SFML/System/Resource.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Resource.inl [moved from SFML-1.6/include/SFML/System/Resource.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/ResourcePtr.inl [moved from SFML-1.6/include/SFML/System/ResourcePtr.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Sleep.hpp [moved from SFML-1.6/include/SFML/System/Sleep.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Thread.hpp [moved from SFML-1.6/include/SFML/System/Thread.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Unicode.hpp [moved from SFML-1.6/include/SFML/System/Unicode.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Unicode.inl [moved from SFML-1.6/include/SFML/System/Unicode.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Unix/Mutex.hpp [moved from SFML-1.6/include/SFML/System/Unix/Mutex.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Unix/Thread.hpp [moved from SFML-1.6/include/SFML/System/Unix/Thread.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Vector2.hpp [moved from SFML-1.6/include/SFML/System/Vector2.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Vector2.inl [moved from SFML-1.6/include/SFML/System/Vector2.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Vector3.hpp [moved from SFML-1.6/include/SFML/System/Vector3.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Vector3.inl [moved from SFML-1.6/include/SFML/System/Vector3.inl with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Win32/Mutex.hpp [moved from SFML-1.6/include/SFML/System/Win32/Mutex.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/System/Win32/Thread.hpp [moved from SFML-1.6/include/SFML/System/Win32/Thread.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window.hpp [moved from SFML-1.6/include/SFML/Window.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/Context.hpp [moved from SFML-1.6/include/SFML/Window/Context.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/Event.hpp [moved from SFML-1.6/include/SFML/Window/Event.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/Input.hpp [moved from SFML-1.6/include/SFML/Window/Input.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/OpenGL.hpp [moved from SFML-1.6/include/SFML/Window/OpenGL.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/VideoMode.hpp [moved from SFML-1.6/include/SFML/Window/VideoMode.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/Window.hpp [moved from SFML-1.6/include/SFML/Window/Window.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/WindowHandle.hpp [moved from SFML-1.6/include/SFML/Window/WindowHandle.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/WindowListener.hpp [moved from SFML-1.6/include/SFML/Window/WindowListener.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/WindowSettings.hpp [moved from SFML-1.6/include/SFML/Window/WindowSettings.hpp with 100% similarity]
dependencies/SFML-1.6/include/SFML/Window/WindowStyle.hpp [moved from SFML-1.6/include/SFML/Window/WindowStyle.hpp with 100% similarity]
dependencies/SFML-1.6/lib/sfml-audio-d.dll [moved from SFML-1.6/lib/sfml-audio-d.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-audio-d.lib [moved from SFML-1.6/lib/sfml-audio-d.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-audio.dll [moved from SFML-1.6/lib/sfml-audio.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-audio.lib [moved from SFML-1.6/lib/sfml-audio.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-graphics-d.dll [moved from SFML-1.6/lib/sfml-graphics-d.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-graphics-d.lib [moved from SFML-1.6/lib/sfml-graphics-d.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-graphics.dll [moved from SFML-1.6/lib/sfml-graphics.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-graphics.lib [moved from SFML-1.6/lib/sfml-graphics.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-system-d.dll [moved from SFML-1.6/lib/sfml-system-d.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-system-d.lib [moved from SFML-1.6/lib/sfml-system-d.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-system.dll [moved from SFML-1.6/lib/sfml-system.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-system.lib [moved from SFML-1.6/lib/sfml-system.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-window-d.dll [moved from SFML-1.6/lib/sfml-window-d.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-window-d.lib [moved from SFML-1.6/lib/sfml-window-d.lib with 100% similarity]
dependencies/SFML-1.6/lib/sfml-window.dll [moved from SFML-1.6/lib/sfml-window.dll with 100% similarity]
dependencies/SFML-1.6/lib/sfml-window.lib [moved from SFML-1.6/lib/sfml-window.lib with 100% similarity]
dependencies/boost.7z [moved from boost.7z with 100% similarity]
dependencies/concrt_extras/agents_extras.h [moved from concrt_extras/agents_extras.h with 100% similarity]
dependencies/concrt_extras/concrt_extras.h [moved from concrt_extras/concrt_extras.h with 100% similarity]
dependencies/concrt_extras/concurrent_unordered_map.h [moved from concrt_extras/concurrent_unordered_map.h with 100% similarity]
dependencies/concrt_extras/concurrent_unordered_set.h [moved from concrt_extras/concurrent_unordered_set.h with 100% similarity]
dependencies/concrt_extras/connect.h [moved from concrt_extras/connect.h with 100% similarity]
dependencies/concrt_extras/internal_concurrent_hash.h [moved from concrt_extras/internal_concurrent_hash.h with 100% similarity]
dependencies/concrt_extras/internal_split_ordered_list.h [moved from concrt_extras/internal_split_ordered_list.h with 100% similarity]
dependencies/ffmpeg 0.8/README.txt [moved from ffmpeg 0.8/README.txt with 100% similarity]
dependencies/ffmpeg 0.8/bin/avcodec-53.dll [moved from ffmpeg 0.8/bin/avcodec-53.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/avdevice-53.dll [moved from ffmpeg 0.8/bin/avdevice-53.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/avfilter-2.dll [moved from ffmpeg 0.8/bin/avfilter-2.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/avformat-53.dll [moved from ffmpeg 0.8/bin/avformat-53.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/avutil-51.dll [moved from ffmpeg 0.8/bin/avutil-51.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/postproc-51.dll [moved from ffmpeg 0.8/bin/postproc-51.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/swresample-0.dll [moved from ffmpeg 0.8/bin/swresample-0.dll with 100% similarity]
dependencies/ffmpeg 0.8/bin/swscale-2.dll [moved from ffmpeg 0.8/bin/swscale-2.dll with 100% similarity]
dependencies/ffmpeg 0.8/doc/developer.html [moved from ffmpeg 0.8/doc/developer.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/faq.html [moved from ffmpeg 0.8/doc/faq.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/ffmpeg.html [moved from ffmpeg 0.8/doc/ffmpeg.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/ffplay.html [moved from ffmpeg 0.8/doc/ffplay.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/ffprobe.html [moved from ffmpeg 0.8/doc/ffprobe.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/general.html [moved from ffmpeg 0.8/doc/general.html with 100% similarity]
dependencies/ffmpeg 0.8/doc/libavfilter.html [moved from ffmpeg 0.8/doc/libavfilter.html with 100% similarity]
dependencies/ffmpeg 0.8/include/inttypes.h [moved from ffmpeg 0.8/include/inttypes.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/avcodec.h [moved from ffmpeg 0.8/include/libavcodec/avcodec.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/avfft.h [moved from ffmpeg 0.8/include/libavcodec/avfft.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/dxva2.h [moved from ffmpeg 0.8/include/libavcodec/dxva2.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/opt.h [moved from ffmpeg 0.8/include/libavcodec/opt.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/vaapi.h [moved from ffmpeg 0.8/include/libavcodec/vaapi.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/vda.h [moved from ffmpeg 0.8/include/libavcodec/vda.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/vdpau.h [moved from ffmpeg 0.8/include/libavcodec/vdpau.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/version.h [moved from ffmpeg 0.8/include/libavcodec/version.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavcodec/xvmc.h [moved from ffmpeg 0.8/include/libavcodec/xvmc.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavdevice/avdevice.h [moved from ffmpeg 0.8/include/libavdevice/avdevice.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavfilter/avcodec.h [moved from ffmpeg 0.8/include/libavfilter/avcodec.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavfilter/avfilter.h [moved from ffmpeg 0.8/include/libavfilter/avfilter.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavfilter/avfiltergraph.h [moved from ffmpeg 0.8/include/libavfilter/avfiltergraph.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavfilter/buffersink.h [moved from ffmpeg 0.8/include/libavfilter/buffersink.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavfilter/vsrc_buffer.h [moved from ffmpeg 0.8/include/libavfilter/vsrc_buffer.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavformat/avformat.h [moved from ffmpeg 0.8/include/libavformat/avformat.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavformat/avio.h [moved from ffmpeg 0.8/include/libavformat/avio.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavformat/version.h [moved from ffmpeg 0.8/include/libavformat/version.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/adler32.h [moved from ffmpeg 0.8/include/libavutil/adler32.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/aes.h [moved from ffmpeg 0.8/include/libavutil/aes.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/attributes.h [moved from ffmpeg 0.8/include/libavutil/attributes.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/audioconvert.h [moved from ffmpeg 0.8/include/libavutil/audioconvert.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/avassert.h [moved from ffmpeg 0.8/include/libavutil/avassert.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/avconfig.h [moved from ffmpeg 0.8/include/libavutil/avconfig.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/avstring.h [moved from ffmpeg 0.8/include/libavutil/avstring.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/avutil.h [moved from ffmpeg 0.8/include/libavutil/avutil.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/base64.h [moved from ffmpeg 0.8/include/libavutil/base64.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/bswap.h [moved from ffmpeg 0.8/include/libavutil/bswap.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/common.h [moved from ffmpeg 0.8/include/libavutil/common.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/cpu.h [moved from ffmpeg 0.8/include/libavutil/cpu.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/crc.h [moved from ffmpeg 0.8/include/libavutil/crc.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/dict.h [moved from ffmpeg 0.8/include/libavutil/dict.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/error.h [moved from ffmpeg 0.8/include/libavutil/error.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/eval.h [moved from ffmpeg 0.8/include/libavutil/eval.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/fifo.h [moved from ffmpeg 0.8/include/libavutil/fifo.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/file.h [moved from ffmpeg 0.8/include/libavutil/file.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/imgutils.h [moved from ffmpeg 0.8/include/libavutil/imgutils.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/intfloat_readwrite.h [moved from ffmpeg 0.8/include/libavutil/intfloat_readwrite.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/intreadwrite.h [moved from ffmpeg 0.8/include/libavutil/intreadwrite.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/lfg.h [moved from ffmpeg 0.8/include/libavutil/lfg.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/log.h [moved from ffmpeg 0.8/include/libavutil/log.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/lzo.h [moved from ffmpeg 0.8/include/libavutil/lzo.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/mathematics.h [moved from ffmpeg 0.8/include/libavutil/mathematics.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/md5.h [moved from ffmpeg 0.8/include/libavutil/md5.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/mem.h [moved from ffmpeg 0.8/include/libavutil/mem.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/opt.h [moved from ffmpeg 0.8/include/libavutil/opt.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/parseutils.h [moved from ffmpeg 0.8/include/libavutil/parseutils.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/pixdesc.h [moved from ffmpeg 0.8/include/libavutil/pixdesc.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/pixfmt.h [moved from ffmpeg 0.8/include/libavutil/pixfmt.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/random_seed.h [moved from ffmpeg 0.8/include/libavutil/random_seed.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/rational.h [moved from ffmpeg 0.8/include/libavutil/rational.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/samplefmt.h [moved from ffmpeg 0.8/include/libavutil/samplefmt.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libavutil/sha.h [moved from ffmpeg 0.8/include/libavutil/sha.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libpostproc/postprocess.h [moved from ffmpeg 0.8/include/libpostproc/postprocess.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libswresample/swresample.h [moved from ffmpeg 0.8/include/libswresample/swresample.h with 100% similarity]
dependencies/ffmpeg 0.8/include/libswscale/swscale.h [moved from ffmpeg 0.8/include/libswscale/swscale.h with 100% similarity]
dependencies/ffmpeg 0.8/lib/avcodec.lib [moved from ffmpeg 0.8/lib/avcodec.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/avdevice.lib [moved from ffmpeg 0.8/lib/avdevice.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/avfilter.lib [moved from ffmpeg 0.8/lib/avfilter.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/avformat.lib [moved from ffmpeg 0.8/lib/avformat.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/avutil.lib [moved from ffmpeg 0.8/lib/avutil.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/postproc.lib [moved from ffmpeg 0.8/lib/postproc.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/swresample.lib [moved from ffmpeg 0.8/lib/swresample.lib with 100% similarity]
dependencies/ffmpeg 0.8/lib/swscale.lib [moved from ffmpeg 0.8/lib/swscale.lib with 100% similarity]
dependencies/ffmpeg 0.8/licenses/bzip2.txt [moved from ffmpeg 0.8/licenses/bzip2.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/ffmpeg.txt [moved from ffmpeg 0.8/licenses/xavs.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/freetype.txt [moved from ffmpeg 0.8/licenses/freetype.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/frei0r.txt [moved from ffmpeg 0.8/licenses/frei0r.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/gsm.txt [moved from ffmpeg 0.8/licenses/gsm.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/lame.txt [moved from ffmpeg 0.8/licenses/lame.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/libvpx.txt [moved from ffmpeg 0.8/licenses/libvpx.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/opencore-amr.txt [moved from ffmpeg 0.8/licenses/opencore-amr.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/openjpeg.txt [moved from ffmpeg 0.8/licenses/openjpeg.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/rtmp.txt [moved from ffmpeg 0.8/licenses/rtmp.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/schroedinger.txt [moved from ffmpeg 0.8/licenses/schroedinger.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/speex.txt [moved from ffmpeg 0.8/licenses/speex.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/theora.txt [moved from ffmpeg 0.8/licenses/theora.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/vorbis.txt [moved from ffmpeg 0.8/licenses/vorbis.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/x264.txt [moved from ffmpeg 0.8/licenses/x264.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/xavs.txt [new file with mode: 0644]
dependencies/ffmpeg 0.8/licenses/xvid.txt [moved from ffmpeg 0.8/licenses/xvid.txt with 100% similarity]
dependencies/ffmpeg 0.8/licenses/zlib.txt [moved from ffmpeg 0.8/licenses/zlib.txt with 100% similarity]
dependencies/glew-1.6.0/LICENSE.txt [moved from glew-1.6.0/LICENSE.txt with 100% similarity]
dependencies/glew-1.6.0/README.txt [moved from glew-1.6.0/README.txt with 100% similarity]
dependencies/glew-1.6.0/TODO.txt [moved from glew-1.6.0/TODO.txt with 100% similarity]
dependencies/glew-1.6.0/bin/glew32.dll [moved from glew-1.6.0/bin/glew32.dll with 100% similarity]
dependencies/glew-1.6.0/bin/glew32mx.dll [moved from glew-1.6.0/bin/glew32mx.dll with 100% similarity]
dependencies/glew-1.6.0/bin/glewinfo.exe [moved from glew-1.6.0/bin/glewinfo.exe with 100% similarity]
dependencies/glew-1.6.0/bin/glewinfo.txt [moved from glew-1.6.0/bin/glewinfo.txt with 100% similarity]
dependencies/glew-1.6.0/bin/visualinfo.exe [moved from glew-1.6.0/bin/visualinfo.exe with 100% similarity]
dependencies/glew-1.6.0/bin/visualinfo.txt [moved from glew-1.6.0/bin/visualinfo.txt with 100% similarity]
dependencies/glew-1.6.0/include/GL/glew.h [moved from glew-1.6.0/include/GL/glew.h with 100% similarity]
dependencies/glew-1.6.0/include/GL/glxew.h [moved from glew-1.6.0/include/GL/glxew.h with 100% similarity]
dependencies/glew-1.6.0/include/GL/wglew.h [moved from glew-1.6.0/include/GL/wglew.h with 100% similarity]
dependencies/glew-1.6.0/lib/glew32.lib [moved from glew-1.6.0/lib/glew32.lib with 100% similarity]
dependencies/glew-1.6.0/lib/glew32mx.lib [moved from glew-1.6.0/lib/glew32mx.lib with 100% similarity]
dependencies/glew-1.6.0/lib/glew32mxs.lib [moved from glew-1.6.0/lib/glew32mxs.lib with 100% similarity]
dependencies/glew-1.6.0/lib/glew32s.lib [moved from glew-1.6.0/lib/glew32s.lib with 100% similarity]
dependencies/tbb/CHANGES [moved from tbb/CHANGES with 100% similarity]
dependencies/tbb/COPYING [moved from tbb/COPYING with 100% similarity]
dependencies/tbb/README [moved from tbb/README with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml/irml.dll [moved from tbb/bin/ia32/vc10/irml/irml.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml/irml.pdb [moved from tbb/bin/ia32/vc10/irml/irml.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml/irml_debug.dll [moved from tbb/bin/ia32/vc10/irml/irml_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml/irml_debug.pdb [moved from tbb/bin/ia32/vc10/irml/irml_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml_c/irml.dll [moved from tbb/bin/ia32/vc10/irml_c/irml.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml_c/irml.pdb [moved from tbb/bin/ia32/vc10/irml_c/irml.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml_c/irml_debug.dll [moved from tbb/bin/ia32/vc10/irml_c/irml_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/irml_c/irml_debug.pdb [moved from tbb/bin/ia32/vc10/irml_c/irml_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb.dll [moved from tbb/bin/ia32/vc10/tbb.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb.pdb [moved from tbb/bin/ia32/vc10/tbb.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_debug.dll [moved from tbb/bin/ia32/vc10/tbb_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_debug.pdb [moved from tbb/bin/ia32/vc10/tbb_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_preview.dll [moved from tbb/bin/ia32/vc10/tbb_preview.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_preview.pdb [moved from tbb/bin/ia32/vc10/tbb_preview.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_preview_debug.dll [moved from tbb/bin/ia32/vc10/tbb_preview_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbb_preview_debug.pdb [moved from tbb/bin/ia32/vc10/tbb_preview_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc.dll [moved from tbb/bin/ia32/vc10/tbbmalloc.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc.pdb [moved from tbb/bin/ia32/vc10/tbbmalloc.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_debug.dll [moved from tbb/bin/ia32/vc10/tbbmalloc_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_debug.pdb [moved from tbb/bin/ia32/vc10/tbbmalloc_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_proxy.dll [moved from tbb/bin/ia32/vc10/tbbmalloc_proxy.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_proxy.pdb [moved from tbb/bin/ia32/vc10/tbbmalloc_proxy.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_proxy_debug.dll [moved from tbb/bin/ia32/vc10/tbbmalloc_proxy_debug.dll with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbmalloc_proxy_debug.pdb [moved from tbb/bin/ia32/vc10/tbbmalloc_proxy_debug.pdb with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbvars.bat [moved from tbb/bin/ia32/vc10/tbbvars.bat with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbvars.csh [moved from tbb/bin/ia32/vc10/tbbvars.csh with 100% similarity]
dependencies/tbb/bin/ia32/vc10/tbbvars.sh [moved from tbb/bin/ia32/vc10/tbbvars.sh with 100% similarity]
dependencies/tbb/bin/tbbvars.bat [moved from tbb/bin/tbbvars.bat with 100% similarity]
dependencies/tbb/include/index.html [moved from tbb/include/index.html with 100% similarity]
dependencies/tbb/include/tbb/_aggregator_internal.h [moved from tbb/include/tbb/_aggregator_internal.h with 100% similarity]
dependencies/tbb/include/tbb/_concurrent_queue_internal.h [moved from tbb/include/tbb/_concurrent_queue_internal.h with 100% similarity]
dependencies/tbb/include/tbb/_concurrent_unordered_internal.h [moved from tbb/include/tbb/_concurrent_unordered_internal.h with 100% similarity]
dependencies/tbb/include/tbb/_item_buffer.h [moved from tbb/include/tbb/_item_buffer.h with 100% similarity]
dependencies/tbb/include/tbb/_tbb_windef.h [moved from tbb/include/tbb/_tbb_windef.h with 100% similarity]
dependencies/tbb/include/tbb/aligned_space.h [moved from tbb/include/tbb/aligned_space.h with 100% similarity]
dependencies/tbb/include/tbb/atomic.h [moved from tbb/include/tbb/atomic.h with 100% similarity]
dependencies/tbb/include/tbb/blocked_range.h [moved from tbb/include/tbb/blocked_range.h with 100% similarity]
dependencies/tbb/include/tbb/blocked_range2d.h [moved from tbb/include/tbb/blocked_range2d.h with 100% similarity]
dependencies/tbb/include/tbb/blocked_range3d.h [moved from tbb/include/tbb/blocked_range3d.h with 100% similarity]
dependencies/tbb/include/tbb/cache_aligned_allocator.h [moved from tbb/include/tbb/cache_aligned_allocator.h with 100% similarity]
dependencies/tbb/include/tbb/combinable.h [moved from tbb/include/tbb/combinable.h with 100% similarity]
dependencies/tbb/include/tbb/compat/condition_variable [moved from tbb/include/tbb/compat/condition_variable with 100% similarity]
dependencies/tbb/include/tbb/compat/ppl.h [moved from tbb/include/tbb/compat/ppl.h with 100% similarity]
dependencies/tbb/include/tbb/compat/thread [moved from tbb/include/tbb/compat/thread with 100% similarity]
dependencies/tbb/include/tbb/compat/tuple [moved from tbb/include/tbb/compat/tuple with 100% similarity]
dependencies/tbb/include/tbb/concurrent_hash_map.h [moved from tbb/include/tbb/concurrent_hash_map.h with 100% similarity]
dependencies/tbb/include/tbb/concurrent_priority_queue.h [moved from tbb/include/tbb/concurrent_priority_queue.h with 100% similarity]
dependencies/tbb/include/tbb/concurrent_queue.h [moved from tbb/include/tbb/concurrent_queue.h with 100% similarity]
dependencies/tbb/include/tbb/concurrent_unordered_map.h [moved from tbb/include/tbb/concurrent_unordered_map.h with 100% similarity]
dependencies/tbb/include/tbb/concurrent_unordered_set.h [moved from tbb/include/tbb/concurrent_unordered_set.h with 100% similarity]
dependencies/tbb/include/tbb/concurrent_vector.h [moved from tbb/include/tbb/concurrent_vector.h with 100% similarity]
dependencies/tbb/include/tbb/critical_section.h [moved from tbb/include/tbb/critical_section.h with 100% similarity]
dependencies/tbb/include/tbb/enumerable_thread_specific.h [moved from tbb/include/tbb/enumerable_thread_specific.h with 100% similarity]
dependencies/tbb/include/tbb/flow_graph.h [moved from tbb/include/tbb/flow_graph.h with 100% similarity]
dependencies/tbb/include/tbb/graph.h [moved from tbb/include/tbb/graph.h with 100% similarity]
dependencies/tbb/include/tbb/index.html [moved from tbb/include/tbb/index.html with 100% similarity]
dependencies/tbb/include/tbb/internal/_aggregator_impl.h [moved from tbb/include/tbb/internal/_aggregator_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_concurrent_queue_impl.h [moved from tbb/include/tbb/internal/_concurrent_queue_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_concurrent_unordered_impl.h [moved from tbb/include/tbb/internal/_concurrent_unordered_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_impl.h [moved from tbb/include/tbb/internal/_flow_graph_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h [moved from tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_join_impl.h [moved from tbb/include/tbb/internal/_flow_graph_join_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_node_impl.h [moved from tbb/include/tbb/internal/_flow_graph_node_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_or_impl.h [moved from tbb/include/tbb/internal/_flow_graph_or_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h [moved from tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h with 100% similarity]
dependencies/tbb/include/tbb/internal/_tbb_windef.h [moved from tbb/include/tbb/internal/_tbb_windef.h with 100% similarity]
dependencies/tbb/include/tbb/machine/gcc_generic.h [moved from tbb/include/tbb/machine/gcc_generic.h with 100% similarity]
dependencies/tbb/include/tbb/machine/ibm_aix51.h [moved from tbb/include/tbb/machine/ibm_aix51.h with 100% similarity]
dependencies/tbb/include/tbb/machine/linux_common.h [moved from tbb/include/tbb/machine/linux_common.h with 100% similarity]
dependencies/tbb/include/tbb/machine/linux_ia32.h [moved from tbb/include/tbb/machine/linux_ia32.h with 100% similarity]
dependencies/tbb/include/tbb/machine/linux_ia64.h [moved from tbb/include/tbb/machine/linux_ia64.h with 100% similarity]
dependencies/tbb/include/tbb/machine/linux_intel64.h [moved from tbb/include/tbb/machine/linux_intel64.h with 100% similarity]
dependencies/tbb/include/tbb/machine/mac_ppc.h [moved from tbb/include/tbb/machine/mac_ppc.h with 100% similarity]
dependencies/tbb/include/tbb/machine/macos_common.h [moved from tbb/include/tbb/machine/macos_common.h with 100% similarity]
dependencies/tbb/include/tbb/machine/sunos_sparc.h [moved from tbb/include/tbb/machine/sunos_sparc.h with 100% similarity]
dependencies/tbb/include/tbb/machine/windows_api.h [moved from tbb/include/tbb/machine/windows_api.h with 100% similarity]
dependencies/tbb/include/tbb/machine/windows_ia32.h [moved from tbb/include/tbb/machine/windows_ia32.h with 100% similarity]
dependencies/tbb/include/tbb/machine/windows_intel64.h [moved from tbb/include/tbb/machine/windows_intel64.h with 100% similarity]
dependencies/tbb/include/tbb/machine/xbox360_ppc.h [moved from tbb/include/tbb/machine/xbox360_ppc.h with 100% similarity]
dependencies/tbb/include/tbb/mutex.h [moved from tbb/include/tbb/mutex.h with 100% similarity]
dependencies/tbb/include/tbb/null_mutex.h [moved from tbb/include/tbb/null_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/null_rw_mutex.h [moved from tbb/include/tbb/null_rw_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_do.h [moved from tbb/include/tbb/parallel_do.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_for.h [moved from tbb/include/tbb/parallel_for.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_for_each.h [moved from tbb/include/tbb/parallel_for_each.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_invoke.h [moved from tbb/include/tbb/parallel_invoke.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_reduce.h [moved from tbb/include/tbb/parallel_reduce.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_scan.h [moved from tbb/include/tbb/parallel_scan.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_sort.h [moved from tbb/include/tbb/parallel_sort.h with 100% similarity]
dependencies/tbb/include/tbb/parallel_while.h [moved from tbb/include/tbb/parallel_while.h with 100% similarity]
dependencies/tbb/include/tbb/partitioner.h [moved from tbb/include/tbb/partitioner.h with 100% similarity]
dependencies/tbb/include/tbb/pipeline.h [moved from tbb/include/tbb/pipeline.h with 100% similarity]
dependencies/tbb/include/tbb/queuing_mutex.h [moved from tbb/include/tbb/queuing_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/queuing_rw_mutex.h [moved from tbb/include/tbb/queuing_rw_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/reader_writer_lock.h [moved from tbb/include/tbb/reader_writer_lock.h with 100% similarity]
dependencies/tbb/include/tbb/recursive_mutex.h [moved from tbb/include/tbb/recursive_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/runtime_loader.h [moved from tbb/include/tbb/runtime_loader.h with 100% similarity]
dependencies/tbb/include/tbb/scalable_allocator.h [moved from tbb/include/tbb/scalable_allocator.h with 100% similarity]
dependencies/tbb/include/tbb/spin_mutex.h [moved from tbb/include/tbb/spin_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/spin_rw_mutex.h [moved from tbb/include/tbb/spin_rw_mutex.h with 100% similarity]
dependencies/tbb/include/tbb/task.h [moved from tbb/include/tbb/task.h with 100% similarity]
dependencies/tbb/include/tbb/task_group.h [moved from tbb/include/tbb/task_group.h with 100% similarity]
dependencies/tbb/include/tbb/task_scheduler_init.h [moved from tbb/include/tbb/task_scheduler_init.h with 100% similarity]
dependencies/tbb/include/tbb/task_scheduler_observer.h [moved from tbb/include/tbb/task_scheduler_observer.h with 100% similarity]
dependencies/tbb/include/tbb/tbb.h [moved from tbb/include/tbb/tbb.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_allocator.h [moved from tbb/include/tbb/tbb_allocator.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_config.h [moved from tbb/include/tbb/tbb_config.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_exception.h [moved from tbb/include/tbb/tbb_exception.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_machine.h [moved from tbb/include/tbb/tbb_machine.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_profiling.h [moved from tbb/include/tbb/tbb_profiling.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_stddef.h [moved from tbb/include/tbb/tbb_stddef.h with 100% similarity]
dependencies/tbb/include/tbb/tbb_thread.h [moved from tbb/include/tbb/tbb_thread.h with 100% similarity]
dependencies/tbb/include/tbb/tbbmalloc_proxy.h [moved from tbb/include/tbb/tbbmalloc_proxy.h with 100% similarity]
dependencies/tbb/include/tbb/tick_count.h [moved from tbb/include/tbb/tick_count.h with 100% similarity]
dependencies/tbb/lib/ia32/vc10/irml/irml.lib [moved from tbb/lib/ia32/vc10/irml/irml.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/irml/irml_debug.lib [moved from tbb/lib/ia32/vc10/irml/irml_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/irml_c/irml.lib [moved from tbb/lib/ia32/vc10/irml_c/irml.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/irml_c/irml_debug.lib [moved from tbb/lib/ia32/vc10/irml_c/irml_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbb.def [moved from tbb/lib/ia32/vc10/tbb.def with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbb.lib [moved from tbb/lib/ia32/vc10/tbb.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbb_debug.lib [moved from tbb/lib/ia32/vc10/tbb_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbb_preview.lib [moved from tbb/lib/ia32/vc10/tbb_preview.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbb_preview_debug.lib [moved from tbb/lib/ia32/vc10/tbb_preview_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbmalloc.def [moved from tbb/lib/ia32/vc10/tbbmalloc.def with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbmalloc.lib [moved from tbb/lib/ia32/vc10/tbbmalloc.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbmalloc_debug.lib [moved from tbb/lib/ia32/vc10/tbbmalloc_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbmalloc_proxy.lib [moved from tbb/lib/ia32/vc10/tbbmalloc_proxy.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbmalloc_proxy_debug.lib [moved from tbb/lib/ia32/vc10/tbbmalloc_proxy_debug.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbproxy.lib [moved from tbb/lib/ia32/vc10/tbbproxy.lib with 100% similarity]
dependencies/tbb/lib/ia32/vc10/tbbproxy_debug.lib [moved from tbb/lib/ia32/vc10/tbbproxy_debug.lib with 100% similarity]
dependencies/zlib/DLL_FAQ.txt [moved from zlib/DLL_FAQ.txt with 100% similarity]
dependencies/zlib/README.txt [moved from zlib/README.txt with 100% similarity]
dependencies/zlib/USAGE.txt [moved from zlib/USAGE.txt with 100% similarity]
dependencies/zlib/include/zconf.h [moved from zlib/include/zconf.h with 100% similarity]
dependencies/zlib/include/zlib.h [moved from zlib/include/zlib.h with 100% similarity]
dependencies/zlib/lib/zdll.lib [moved from zlib/lib/zdll.lib with 100% similarity]
dependencies/zlib/lib/zlib.def [moved from zlib/lib/zlib.def with 100% similarity]
dependencies/zlib/zlib1.dll [moved from zlib/zlib1.dll with 100% similarity]
modules/bluefish/StdAfx.cpp [new file with mode: 0644]
modules/bluefish/StdAfx.h [new file with mode: 0644]
modules/bluefish/bluefish.cpp [new file with mode: 0644]
modules/bluefish/bluefish.h [new file with mode: 0644]
modules/bluefish/bluefish.vcxproj [new file with mode: 0644]
modules/bluefish/bluefish.vcxproj.filters [new file with mode: 0644]
modules/bluefish/consumer/bluefish_consumer.cpp [new file with mode: 0644]
modules/bluefish/consumer/bluefish_consumer.h [new file with mode: 0644]
modules/bluefish/util/blue_velvet.cpp [new file with mode: 0644]
modules/bluefish/util/blue_velvet.h [new file with mode: 0644]
modules/bluefish/util/memory.h [new file with mode: 0644]
modules/decklink/StdAfx.cpp [new file with mode: 0644]
modules/decklink/StdAfx.h [new file with mode: 0644]
modules/decklink/consumer/decklink_consumer.cpp [new file with mode: 0644]
modules/decklink/consumer/decklink_consumer.h [new file with mode: 0644]
modules/decklink/decklink.cpp [new file with mode: 0644]
modules/decklink/decklink.h [new file with mode: 0644]
modules/decklink/decklink.vcxproj [new file with mode: 0644]
modules/decklink/decklink.vcxproj.filters [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPI.idl [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPIVersion.h [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPI_v7_1.idl [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPI_v7_3.idl [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPI_v7_6.idl [new file with mode: 0644]
modules/decklink/interop/DeckLinkAPI_v7_9.idl [new file with mode: 0644]
modules/decklink/producer/decklink_producer.cpp [new file with mode: 0644]
modules/decklink/producer/decklink_producer.h [new file with mode: 0644]
modules/decklink/util/util.h [new file with mode: 0644]
modules/ffmpeg/StdAfx.cpp [new file with mode: 0644]
modules/ffmpeg/StdAfx.h [new file with mode: 0644]
modules/ffmpeg/consumer/ffmpeg_consumer.cpp [new file with mode: 0644]
modules/ffmpeg/consumer/ffmpeg_consumer.h [new file with mode: 0644]
modules/ffmpeg/ffmpeg.cpp [new file with mode: 0644]
modules/ffmpeg/ffmpeg.h [new file with mode: 0644]
modules/ffmpeg/ffmpeg.vcxproj [new file with mode: 0644]
modules/ffmpeg/ffmpeg.vcxproj.filters [new file with mode: 0644]
modules/ffmpeg/ffmpeg_error.h [new file with mode: 0644]
modules/ffmpeg/producer/audio/audio_decoder.cpp [new file with mode: 0644]
modules/ffmpeg/producer/audio/audio_decoder.h [new file with mode: 0644]
modules/ffmpeg/producer/audio/audio_resampler.cpp [new file with mode: 0644]
modules/ffmpeg/producer/audio/audio_resampler.h [new file with mode: 0644]
modules/ffmpeg/producer/ffmpeg_producer.cpp [new file with mode: 0644]
modules/ffmpeg/producer/ffmpeg_producer.h [new file with mode: 0644]
modules/ffmpeg/producer/filter/filter.cpp [new file with mode: 0644]
modules/ffmpeg/producer/filter/filter.h [new file with mode: 0644]
modules/ffmpeg/producer/filter/parallel_yadif.cpp [new file with mode: 0644]
modules/ffmpeg/producer/filter/parallel_yadif.h [new file with mode: 0644]
modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp [new file with mode: 0644]
modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h [new file with mode: 0644]
modules/ffmpeg/producer/input/input.cpp [new file with mode: 0644]
modules/ffmpeg/producer/input/input.h [new file with mode: 0644]
modules/ffmpeg/producer/muxer/display_mode.h [new file with mode: 0644]
modules/ffmpeg/producer/muxer/frame_muxer.cpp [new file with mode: 0644]
modules/ffmpeg/producer/muxer/frame_muxer.h [new file with mode: 0644]
modules/ffmpeg/producer/tbb_avcodec.cpp [new file with mode: 0644]
modules/ffmpeg/producer/tbb_avcodec.h [new file with mode: 0644]
modules/ffmpeg/producer/util/flv.cpp [new file with mode: 0644]
modules/ffmpeg/producer/util/flv.h [new file with mode: 0644]
modules/ffmpeg/producer/util/util.cpp [new file with mode: 0644]
modules/ffmpeg/producer/util/util.h [new file with mode: 0644]
modules/ffmpeg/producer/video/video_decoder.cpp [new file with mode: 0644]
modules/ffmpeg/producer/video/video_decoder.h [new file with mode: 0644]
modules/flash/StdAfx.cpp [new file with mode: 0644]
modules/flash/StdAfx.h [new file with mode: 0644]
modules/flash/flash.cpp [new file with mode: 0644]
modules/flash/flash.h [new file with mode: 0644]
modules/flash/flash.vcxproj [new file with mode: 0644]
modules/flash/flash.vcxproj.filters [new file with mode: 0644]
modules/flash/interop/Flash9e.IDL [new file with mode: 0644]
modules/flash/interop/Flash9e_i.c [new file with mode: 0644]
modules/flash/interop/TimerHelper.h [new file with mode: 0644]
modules/flash/interop/axflash.h [new file with mode: 0644]
modules/flash/producer/FlashAxContainer.cpp [new file with mode: 0644]
modules/flash/producer/FlashAxContainer.h [new file with mode: 0644]
modules/flash/producer/cg_producer.cpp [new file with mode: 0644]
modules/flash/producer/cg_producer.h [new file with mode: 0644]
modules/flash/producer/flash_producer.cpp [new file with mode: 0644]
modules/flash/producer/flash_producer.h [new file with mode: 0644]
modules/flash/util/swf.cpp [new file with mode: 0644]
modules/flash/util/swf.h [new file with mode: 0644]
modules/image/consumer/image_consumer.cpp [new file with mode: 0644]
modules/image/consumer/image_consumer.h [new file with mode: 0644]
modules/image/image.cpp [new file with mode: 0644]
modules/image/image.h [new file with mode: 0644]
modules/image/image.vcxproj [new file with mode: 0644]
modules/image/image.vcxproj.filters [new file with mode: 0644]
modules/image/producer/image_producer.cpp [new file with mode: 0644]
modules/image/producer/image_producer.h [new file with mode: 0644]
modules/image/producer/image_scroll_producer.cpp [new file with mode: 0644]
modules/image/producer/image_scroll_producer.h [new file with mode: 0644]
modules/image/util/image_algorithms.h [new file with mode: 0644]
modules/image/util/image_loader.cpp [new file with mode: 0644]
modules/image/util/image_loader.h [new file with mode: 0644]
modules/image/util/image_view.h [new file with mode: 0644]
modules/oal/consumer/oal_consumer.cpp [new file with mode: 0644]
modules/oal/consumer/oal_consumer.h [new file with mode: 0644]
modules/oal/oal.cpp [new file with mode: 0644]
modules/oal/oal.h [new file with mode: 0644]
modules/oal/oal.vcxproj [new file with mode: 0644]
modules/oal/oal.vcxproj.filters [new file with mode: 0644]
modules/ogl/consumer/ogl_consumer.cpp [new file with mode: 0644]
modules/ogl/consumer/ogl_consumer.h [new file with mode: 0644]
modules/ogl/ogl.cpp [new file with mode: 0644]
modules/ogl/ogl.h [new file with mode: 0644]
modules/ogl/ogl.vcxproj [new file with mode: 0644]
modules/ogl/ogl.vcxproj.filters [new file with mode: 0644]
modules/silverlight/StdAfx.cpp [new file with mode: 0644]
modules/silverlight/StdAfx.h [new file with mode: 0644]
modules/silverlight/interop/XcpControlHost.cpp [new file with mode: 0644]
modules/silverlight/interop/XcpControlHost.h [new file with mode: 0644]
modules/silverlight/interop/XcpPropertyBag.cpp [new file with mode: 0644]
modules/silverlight/interop/XcpPropertyBag.h [new file with mode: 0644]
modules/silverlight/interop/xcpctrl.h [new file with mode: 0644]
modules/silverlight/interop/xcpctrl.idl [new file with mode: 0644]
modules/silverlight/interop/xcpctrl_h.h [new file with mode: 0644]
modules/silverlight/interop/xcpctrl_i.c [new file with mode: 0644]
modules/silverlight/interop/xcpctrl_p.c [new file with mode: 0644]
modules/silverlight/producer/silverlight_producer.cpp [new file with mode: 0644]
modules/silverlight/producer/silverlight_producer.h [new file with mode: 0644]
modules/silverlight/silverlight.cpp [new file with mode: 0644]
modules/silverlight/silverlight.h [new file with mode: 0644]
modules/silverlight/silverlight.vcxproj [new file with mode: 0644]
modules/silverlight/silverlight.vcxproj.filters [new file with mode: 0644]
protocol/StdAfx.cpp [new file with mode: 0644]
protocol/StdAfx.h [new file with mode: 0644]
protocol/amcp/AMCPCommand.h [new file with mode: 0644]
protocol/amcp/AMCPCommandQueue.cpp [new file with mode: 0644]
protocol/amcp/AMCPCommandQueue.h [new file with mode: 0644]
protocol/amcp/AMCPCommandsImpl.cpp [new file with mode: 0644]
protocol/amcp/AMCPCommandsImpl.h [new file with mode: 0644]
protocol/amcp/AMCPProtocolStrategy.cpp [new file with mode: 0644]
protocol/amcp/AMCPProtocolStrategy.h [new file with mode: 0644]
protocol/cii/CIICommand.h [new file with mode: 0644]
protocol/cii/CIICommandsImpl.cpp [new file with mode: 0644]
protocol/cii/CIICommandsImpl.h [new file with mode: 0644]
protocol/cii/CIIProtocolStrategy.cpp [new file with mode: 0644]
protocol/cii/CIIProtocolStrategy.h [new file with mode: 0644]
protocol/clk/CLKProtocolStrategy.cpp [new file with mode: 0644]
protocol/clk/CLKProtocolStrategy.h [new file with mode: 0644]
protocol/clk/clk_command_processor.cpp [new file with mode: 0644]
protocol/clk/clk_command_processor.h [new file with mode: 0644]
protocol/clk/clk_commands.cpp [new file with mode: 0644]
protocol/clk/clk_commands.h [new file with mode: 0644]
protocol/protocol.vcxproj [new file with mode: 0644]
protocol/protocol.vcxproj.filters [new file with mode: 0644]
protocol/util/AsyncEventServer.cpp [new file with mode: 0644]
protocol/util/AsyncEventServer.h [new file with mode: 0644]
protocol/util/ClientInfo.h [new file with mode: 0644]
protocol/util/ProtocolStrategy.h [new file with mode: 0644]
protocol/util/SocketInfo.cpp [new file with mode: 0644]
protocol/util/SocketInfo.h [new file with mode: 0644]
protocol/util/Thread.cpp [new file with mode: 0644]
protocol/util/Thread.h [new file with mode: 0644]
protocol/util/stateful_protocol_strategy_wrapper.cpp [new file with mode: 0644]
protocol/util/stateful_protocol_strategy_wrapper.h [new file with mode: 0644]
shell/CasparCG.ico [new file with mode: 0644]
shell/casparcg.config [new file with mode: 0644]
shell/main.cpp [new file with mode: 0644]
shell/resource.h [new file with mode: 0644]
shell/server.cpp [new file with mode: 0644]
shell/server.h [new file with mode: 0644]
shell/shell.rc [new file with mode: 0644]
shell/shell.vcxproj [new file with mode: 0644]
shell/shell.vcxproj.filters [new file with mode: 0644]
version.tmpl [new file with mode: 0644]

diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644 (file)
index 0000000..7c33485
--- /dev/null
@@ -0,0 +1,415 @@
+CasparCG 2.0.4 Stable (w.r.t 2.0.3 Stable)\r
+==========================================\r
+\r
+General\r
+-------\r
+\r
+  o Logging output now includes milliseconds and has modified format:\r
+    yyyy-mm-d HH:MM:SS.ZZZ\r
+  o Added support for generating thumbnails for media files. Currently only\r
+    video files and images are supported. By default the media directory is\r
+       scanned every 5 seconds for new/modified/removed files and thumbnails are\r
+       generated/regenerated/removed accordingly.\r
+\r
+Layer\r
+-----\r
+\r
+  o Fixed a problem where the first frame was not always shown on LOAD.\r
+\r
+Audio mixer\r
+-----------\r
+\r
+  o Added support for a master volume mixer setting for each channel.\r
+\r
+Consumers\r
+---------\r
+\r
+  o Simplified implementation of bluefish consumer, with regards to\r
+  o Avoid that the ffmpeg consumer blocks the channel output when it can't keep\r
+    up with the frame rate (drops instead).\r
+  o Added support for to create a separate key and fill file when recording with\r
+    the ffmpeg consumer. Add the SEPARATE_KEY parameter to the ffmpeg consumer\r
+       parameter list. The key file will get the _A suffix to be picked up by the\r
+       separated_producer when doing playback.\r
+  o The image consumer now writes to the media folder instead of the data\r
+    folder.\r
+\r
+Producers\r
+---------\r
+\r
+  o Added support for playing .swf files using the flash producer.\r
+\r
+AMCP\r
+----\r
+\r
+  o The master volume feature is controlled via the MASTERVOLUME MIXER\r
+    parameter. Example: MIXER 1 MASTERVOLUME 0.5\r
+  o THUMBNAIL LIST/RETRIEVE/GENERATE/GENERATE_ALL command was added to support\r
+    the thumbnail feature.\r
+  o ADD 1 FILE output.mov SEPARETE_KEY activates the separate key feature of the\r
+    ffmpeg consumer creating an additional output_a.mov containing only the key.\r
+  o Added KILL command for shutting down the server without console access.\r
+\r
+CasparCG 2.0.3 Stable (w.r.t 2.0.3 Alpha)\r
+=========================================\r
+\r
+Stage\r
+-----\r
+\r
+  o Fixed dead-lock that can occur with multiple mixer tweens.\r
+\r
+AMCP\r
+----\r
+\r
+  o DATA STORE now supports creating folders of path specified if they does not\r
+    exist.\r
+  o DATA REMOVE command was added.\r
+\r
+CasparCG 2.0.3 Alpha (w.r.t 2.0 Stable)\r
+=======================================\r
+\r
+General\r
+-------\r
+\r
+  o Data files are now stored in UTF-8 with BOM. Latin1 files are still\r
+    supported for backwards compatibility\r
+  o Commands written in UTF-8 to log file but only ascii characters to console.\r
+  o Added supported video formats:\r
+    + 720p2398 (not supported by decklink)\r
+    + 720p2400 (not supported by decklink)\r
+    + 1080p5994\r
+    + 1080p6000\r
+    + 720p30 (not supported by decklink)\r
+    + 720p29.976 (not supported by decklink)\r
+\r
+CLK\r
+---\r
+\r
+  o CLK protocol implementation can now serve more than one connection at a time\r
+    safely.\r
+  o Added timeline support to the CLK protocol.\r
+  o Refactored parts of the CLK parser implementation.\r
+\r
+Consumers\r
+---------\r
+\r
+  o Consumers on same channel now invoked asynchronously to allow for proper\r
+    sync of multiple consumers.\r
+  o System audio consumer:\r
+    + no longer provides sync to caspar.\r
+  o Screen consumer:\r
+    + Support for multiple screen consumers on the same channel\r
+    + No longer spin-waits for vsync\r
+    + Now deinterlaces to two separate frames so for example 50i will no longer\r
+      be converted to 25p but instead to 50p for smooth playback of interlaced\r
+      content.\r
+  o Decklink consumer now logs whether a reference signal is detected or not.\r
+\r
+Producers\r
+---------\r
+\r
+  o Image scroll producer:\r
+    + Field-rate motion instead of frame-rate motion with interlaced video\r
+      formats. This can be overridden by giving the PROGRESSIVE parameter.\r
+    + SPEED parameter now defines pixels per frame/field instead of half pixels\r
+      per frame. The scrolling direction is also reversed so SPEED 0.5 is the\r
+      previous equivalent of SPEED -1. Movements are done with subpixel accuracy\r
+    + Fixed incorrect starting position of image.\r
+    + Rounding error fixes to allow for more exact scrolling.\r
+    + Added support for motion blur via a new BLUR parameter\r
+    + Added PREMULTIPLY parameter to support images stored with straight alpha.\r
+\r
+CasparCG 2.0 Stable (w.r.t Beta 3)\r
+==================================\r
+\r
+General\r
+-------\r
+\r
+  o Misc stability and performance fixes.\r
+\r
+Consumers\r
+---------\r
+\r
+  o File Consumer\r
+    + Changed semantics to more closely follow ffmpeg (see forums).\r
+    + Added options, -r, -acodec, -s, -pix_fmt, -f and more.\r
+  o Screen Consumer\r
+    + Added vsync support.\r
+\r
+CasparCG 2.0 Beta 3 (w.r.t Beta 1)\r
+==================================\r
+\r
+Formats\r
+-------\r
+\r
+  o ProRes Support\r
+    + Both encoding and decoding.\r
+  o NTSC Support\r
+    + Updated audio-pipeline for native NTSC support. Previous implementation\r
+      did not fully support NTSC audio and could cause incorrect behaviour or\r
+      even crashes.\r
+\r
+Consumers\r
+---------\r
+\r
+  o File Consumer added\r
+    + See updated wiki or ask in forum for more information.\r
+    + Should support anything ffmpeg supports. However, we will work mainly with\r
+      DNXHD, PRORES and H264.\r
+    - Key-only is not supported.\r
+  o Bluefish Consumer\r
+    + 24 bit audio support.\r
+    - Embedded-audio does not work with Epoch cards.\r
+  o Decklink Consumer\r
+    + Low latency enabled by default.\r
+    + Added graphs for driver buffers.\r
+  o Screen Consumer\r
+    + Changed screen consumer square PAL to the more common wide-square PAL.\r
+    + Can now be closed.\r
+    + Fixed interpolation artifacts when running non-square video-modes.\r
+    + Automatically deinterlace interlaced input.\r
+\r
+Producers\r
+---------\r
+\r
+  o Decklink Producer\r
+    + Improved color quality be avoiding uneccessary conversion to BGRA.\r
+  o FFMPEG Producer\r
+    + Fixed missing alpha for (RGB)A formats when deinterlacing.\r
+    + Updated buffering to work better with files with long audio/video\r
+      interleaving.\r
+    + Seekable while running and after reaching EOF. CALL 1-1 SEEK 200.\r
+    + Enable/disable/query looping while running. CALL 1-1 LOOP 1.\r
+    + Fixed bug with duration calculation.\r
+    + Fixed bug with fps calculation.\r
+    + Improved auto-transcode accuracy.\r
+    + Improved seeking accuracy.\r
+    + Fixed bug with looping and LENGTH.\r
+    + Updated to newer ffmpeg version.\r
+    + Fixed incorrect scaling of NTSC DV files.\r
+    + Optimized color conversion when using YADIF filters.\r
+  o Flash Producer\r
+    + Release flash-player when empty.\r
+    + Use native resolution template-host.\r
+    + Template-hosts are now choosen automatically if not configured. The\r
+      template-host with the corresponding video-mode name is now chosen.\r
+    + Use square pixel dimensions.\r
+\r
+AMCP\r
+----\r
+\r
+  o When possible, commands will no longer wait for rendering pipeline. This\r
+    reduces command execution latencies, especially when sending a lot of\r
+    commands in a short timespan.\r
+  o Fixed CINF command.\r
+  o ADD/REMOVE no longer require subindex,\r
+    e.g. "ADD 1 SCREEN" / "REMOVE 1 SCREEN" instead of "ADD 1-1 SCREEN" / ...\r
+  o PARAM is renamed to CALL.\r
+  o STATUS command is replaced by INFO.\r
+  o INFO command has been extended:\r
+    + INFO (lists channels).\r
+    + INFO 1 (channel info).\r
+    + INFO 1-1 (layer info).\r
+    + INFO 1-1 F (foreground producer info).\r
+    + INFO 1-1 B (background producer info).\r
+    + INFO TEMPLATE mytemplate (template meta-data info, e.g. field names).\r
+  o CG INFO command has been extended.\r
+    + CG INFO 1 (template-host information, e.g. what layers are occupied).\r
+\r
+Mixer\r
+-----\r
+\r
+  o Fixed alpha with blend modes.\r
+  o Automatically deinterlace for MIXER FILL commands.\r
+\r
+Channel\r
+-------\r
+\r
+  o SET MODE now reverts back to old video-mode on failure.\r
+\r
+Diagnostics\r
+-----------\r
+\r
+  o Improved graphs and added more status information.\r
+  o Print configuration into log at startup.\r
+  o Use the same log file for the entire day, instead of one per startup as\r
+    previously.\r
+  o Diagnostics window is now closable.\r
+\r
+Configuration\r
+-------------\r
+\r
+  o Simplified.\r
+\r
+CasparCG 2.0 Beta 1 (w.r.t Alpha)\r
+=================================\r
+\r
+  o Blending Modes (needs to be explicitly enabled)\r
+    + overlay\r
+    + screen\r
+    + multiply\r
+    + and many more.\r
+  o Added additive keyer in addition to linear keyer.\r
+  o Image adjustements\r
+    + saturation\r
+    + brightness\r
+    + contrast\r
+    + min input-level\r
+    + max input-level\r
+    + min output-level\r
+    + max output-level\r
+    + gamma\r
+  o Support for ffmpeg-filters such as (ee http://ffmpeg.org/libavfilter.html)\r
+    + yadif deinterlacer (optimized in CasparCG for full multi-core support)\r
+    + de-noising\r
+    + dithering\r
+    + box blur\r
+    + and many more\r
+  o 32-bit SSE optimized audio pipeline.\r
+  o Decklink-Consumer uses external-key by default.\r
+  o Decklink-Consumer has 32 bit embedded-audio support.\r
+  o Decklink-Producer has 32 bit embedded-audio support.\r
+  o LOADBG with AUTO feature which automatically playes queued clip when\r
+    foreground clip has ended.\r
+  o STATUS command for layers.\r
+  o LOG LEVEL command for log filtering.\r
+  o MIX transitation work with transparent clips.\r
+  o Freeze on last frame.\r
+  o Producer buffering is now configurable.\r
+  o Consumer buffering is now configurable.\r
+  o Now possible to configure template-hosts for different video-modes.\r
+  o Added auto transcoder for ffmpeg-producer which automatically transcodes\r
+    input video into compatible video format for the channel.\r
+    + interlacing (50p -> 50i)\r
+    + deinterlacing (50i -> 25p)\r
+    + bob-deinterlacing (50i -> 50p)\r
+    + bob-deinterlacing and reinterlacing (w1xh150i -> w2xh250i)\r
+    + doubling (25p -> 50p)\r
+    + halfing (50p -> 25p)\r
+    + field-order swap (upper <-> lower)\r
+  o Screen consumer now automatically deinterlaces when receiveing interlaced\r
+    content.\r
+  o Optimized renderer.\r
+  o Renderer can now be run asynchronously with producer by using a\r
+    producer-buffer size greater than 0.\r
+  o Improved error and crash recovery.\r
+  o Improved logging.\r
+  o Added Image-Scroll-Producer\r
+  o Key-only has now near zery performance overhead.\r
+  o Reduced memory requirements\r
+  o Removed "warm up lag" which occured when playing the first media clip after\r
+    the server has started.\r
+  o Added read-back fence for OpenGL device for improved multi-channel\r
+    performance.\r
+  o Memory support increased from standard 2 GB to 4 GB on 64 bit Win 7 OS.\r
+  o Added support for 2* Decklink cards in FullHD.\r
+  o Misc bugs fixes and performance improvements.\r
+  o Color producer now support some color codes in addition to color codes, e.g.\r
+    EMPTY, BLACK, RED etc...\r
+  o Alpha value in color codes is now optional.\r
+  o More than 2 Decklink cards might be possible but have not yet been tested.\r
+\r
+CasparCG 2.0 Alpha (w.r.t 1.8)\r
+==============================\r
+\r
+General\r
+-------\r
+\r
+  o Mayor refactoring for improved readability and mainainability.\r
+  o Some work towards platorm-independence. Currently the greatest challenge for\r
+    full platform-independence is flash-producer.\r
+  o Misc improved scalability.\r
+  o XML-configuration.\r
+  o Decklink\r
+    + Support for multiple decklink-cards.\r
+\r
+Core\r
+----\r
+\r
+  o Multiple producers per video_channel.\r
+  o Multiple consumers per video_channel.\r
+  o Swap producers between layers and channels during run-time.\r
+  o Support for upper-field and lower-field interlacing.\r
+  o Add and remove consumers during run-time.\r
+  o Preliminary support for NTSC.\r
+\r
+AMCP\r
+----\r
+\r
+  o Query flash and template-host version.\r
+  o Recursive media-folder listing.\r
+  o Misc changes.\r
+\r
+Mixer\r
+-----\r
+\r
+  o Animated tween transforms.\r
+  o Image-Mixer\r
+    + Fully GPU accelerated (all features listed below are done on the gpu),\r
+    + Layer composition.\r
+    + Colorspaces (rgba, bgra, argb, yuv, yuva, yuv-hd, yuva-hd).\r
+    + Interlacing.\r
+    + Per-layer image-transforms:\r
+      + Opacity\r
+      + Gain\r
+      + Scaling\r
+      + Clipping\r
+      + Translation\r
+  o Audio-Mixer\r
+    + Per-layer and per-sample audio-transforms:\r
+        + Gain\r
+    + Fully internal audio-mixing. Single output-video_channel.\r
+\r
+Consumers\r
+---------\r
+\r
+  o Decklink-Consumer\r
+    + Embedded audio.\r
+    + HD support.\r
+    + Hardware clock.\r
+  o Bluefish-Consumer\r
+    + Drivers are loaded on-demand (server now runs on computers without\r
+      installed bluefish-drivers).\r
+    + Embedded-audio.\r
+    + Allocated frames are no longer leaked.\r
+\r
+Producers\r
+---------\r
+\r
+  o Decklink-Producer\r
+    + Embedded audio.\r
+    + HD support.\r
+  o Color-Producer\r
+    + GPU accelerated.\r
+  o FFMPEG-Producer\r
+    + Asynchronous file IO.\r
+    + Parallel decoding of audio and video.\r
+    + Colorspace transform are moved to gpu.\r
+  o Transition-Producer\r
+    + Fully interlaced transition (previsously only progressive, even when\r
+      running in interlaced mode).\r
+    + Per-sample mixing between source and destination clips.\r
+    + Tween transitions.\r
+  o Flash-Producer\r
+    + DirectDraw access (sligthly improved performance).\r
+    + Improved time-sync. Smoother animations and proper interlacing.\r
+  o Image-Producer\r
+    + Support for various imageformats through FreeImage library.\r
+\r
+Diagnostics\r
+-----------\r
+\r
+  o Graphs for monitoring performance and events.\r
+  o Misc logging improvements.\r
+  o Seperate log-file for every run of the server.\r
+  o Error logging provides full exception details, instead of only printing that\r
+    an error has occured.\r
+  o Console with real-time logging output.\r
+  o Console with AMCP input.\r
+\r
+Removed\r
+-------\r
+\r
+  o Registry-configuration (replaced by XML-Configuration).\r
+  o TGA-Producer (replaced by Image-Producer).\r
+  o TGA-Scroll-Producer\r
similarity index 100%
rename from ffmpeg 0.8/licenses/ffmpeg.txt
rename to LICENSE.txt
diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..23b0863
--- /dev/null
@@ -0,0 +1,111 @@
+================================================================================\r
+CasparCG Server 2.0.3\r
+================================================================================\r
+\r
+SYSTEM REQUIREMENTS\r
+===================\r
+\r
+1. Intel processor (while AMD processors should work, CasparCG Server has only\r
+   been tested on Intel processors.)\r
+\r
+2. We recommend Windows 7 (64-bit,) but it has also been successfully used on \r
+   Windows 7 (32-bit) and Windows XP SP2 (32-bit only.)\r
+   \r
+3. An OpenGL 3.0-capable graphics card from NVIDIA is required to run \r
+   CasparCG Server 2.0. Also make sure that you have installed the latest\r
+   drivers.\r
+   Please check your card's capabilities at: \r
+   http://en.wikipedia.org/wiki/Comparison_of_Nvidia_graphics_processing_units\r
+   Graphics cards from other manufacturers _may_ work but have not been tested.\r
+\r
+4. Microsoft Visual C++ 2010 Redistributable Package must be installed.\r
+   Free download at:\r
+   http://www.microsoft.com/download/en/details.aspx?id=5555\r
+\r
+5. You must have Flash Player 10.3 or later installed (an installer can be found\r
+   in the "Flash Player Installation" folder.)\r
+\r
+The latest recommendations are available at:\r
+http://casparcg.com/wiki/CasparCG_Server#System_Requirements\r
+\r
+\r
+INSTALLATION\r
+============\r
+\r
+1. Check that your system meets the requirements.\r
+\r
+2. Unzip and place the CasparCG Server 2.0.3 folder anywhere you like.\r
+\r
+3. Install "Microsoft Visual C++ 2010 Redistributable Package" from\r
+   http://www.microsoft.com/download/en/details.aspx?id=5555\r
+   \r
+4. Install "Flash Player 10.3.183.14" from the "Flash Player Installation"\r
+   folder.\r
+\r
+5. Make sure you turn off Windows' Aero Theme as it interferes with \r
+   CasparCG Server's OpenGL features!\r
+\r
+6. Configure the server settings in the "casparcg.config" text file.\r
+\r
+7. Start the "CasparCG.exe" program.\r
+\r
+8. Connect to the server from a client, such as the included CasparCG 2.0 Demo\r
+   Client (requires Adobe AIR.)\r
+\r
+\r
+DOCUMENTATION\r
+=============\r
+\r
+The most up-to-date documentation is always available at\r
+http://casparcg.com/wiki/\r
+\r
+\r
+CONFIGURATION\r
+=============\r
+\r
+By default, CasparCG Server will look in the media folder for videos, audio and\r
+images files. Flash templates are stored in the templates folder. If you want to\r
+change the location (for example to a faster disk) you just change the paths in\r
+the casparcg.config file.\r
+\r
+* How to enable Screen consumer:\r
+\r
+  Open casparcg.config and use the following node for consumers:\r
+\r
+  <consumers>\r
+      <screen/>\r
+  </consumers>\r
+\r
+* How to enable a DeckLink card and how to get video in and key output:\r
+\r
+  Open casparcg.config and use the following node for consumers:\r
+\r
+  <consumers>\r
+      <decklink/>\r
+  </consumers>\r
+\r
+# Tip:\r
+\r
+At the bottom of the casparcg.config file you will find comments which document\r
+additional settings.\r
+\r
+\r
+LICENSING\r
+=========\r
+\r
+CasparCG Server is distributed under the GNU General Public License GPLv3 or\r
+higher, see LICENSE.TXT for details.\r
+\r
+CREDITS - People who have contributed to the CasparCG Project\r
+==========(sorted alphabetically by last name)===============\r
+\r
+Niklas  Andersson\r
+Jonas   Hummelstrand    (jonas.hummelstrand@svt.se)\r
+Andreas Jeansson        (andreas.jeansson@svt.se)\r
+Peter   Karlsson        (peter.p.karlsson@svt.se)\r
+Jeff    Lafforgue\r
+Andy    Mace\r
+Robert         Nagy            (ronag89@gmail.com)\r
+Helge   Norberg         (helge.norberg@svt.se)\r
+Thomas  R. Kaltz III\r
+Olle    Soprani\r
diff --git a/casparcg.sln b/casparcg.sln
new file mode 100644 (file)
index 0000000..d634fe3
--- /dev/null
@@ -0,0 +1,148 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 11.00\r
+# Visual Studio 2010\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "core\core.vcxproj", "{79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shell", "shell\shell.vcxproj", "{8C26C94F-8092-4769-8D84-DEA479721C5B}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protocol", "protocol\protocol.vcxproj", "{2040B361-1FB6-488E-84A5-38A580DA90DE}"\r
+EndProject\r
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "documentation", "documentation", "{32079541-68ED-4319-91FB-0FF041642679}"\r
+       ProjectSection(SolutionItems) = preProject\r
+               CHANGES.txt = CHANGES.txt\r
+               LICENSE.txt = LICENSE.txt\r
+               README.txt = README.txt\r
+       EndProjectSection\r
+EndProject\r
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{C54DA43E-4878-45DB-B76D-35970553672C}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bluefish", "modules\bluefish\bluefish.vcxproj", "{69313D25-9F54-4FC9-9872-628A4DD79464}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decklink", "modules\decklink\decklink.vcxproj", "{D3611658-8F54-43CF-B9AF-A5CF8C1102EA}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ffmpeg", "modules\ffmpeg\ffmpeg.vcxproj", "{F6223AF3-BE0B-4B61-8406-98922CE521C2}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flash", "modules\flash\flash.vcxproj", "{816DEABA-3757-4306-AFE0-C27CF96C4DEA}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oal", "modules\oal\oal.vcxproj", "{82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ogl", "modules\ogl\ogl.vcxproj", "{88F974F0-D09F-4788-8CF8-F563209E60C1}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image", "modules\image\image.vcxproj", "{3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{02308602-7FE0-4253-B96E-22134919F56A}"\r
+EndProject\r
+Global\r
+       GlobalSection(SubversionScc) = preSolution\r
+               Svn-Managed = True\r
+               Manager = AnkhSVN - Subversion Support for Visual Studio\r
+       EndGlobalSection\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Win32 = Debug|Win32\r
+               Develop|Win32 = Develop|Win32\r
+               Profile|Win32 = Profile|Win32\r
+               Release|Win32 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|Win32.Build.0 = Debug|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Develop|Win32.Build.0 = Develop|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Profile|Win32.Build.0 = Profile|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|Win32.ActiveCfg = Release|Win32\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|Win32.Build.0 = Release|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|Win32.Build.0 = Debug|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Develop|Win32.Build.0 = Develop|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Profile|Win32.Build.0 = Profile|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|Win32.ActiveCfg = Release|Win32\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|Win32.Build.0 = Release|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|Win32.Build.0 = Debug|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Develop|Win32.Build.0 = Develop|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Profile|Win32.Build.0 = Profile|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|Win32.ActiveCfg = Release|Win32\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|Win32.Build.0 = Release|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|Win32.Build.0 = Debug|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Develop|Win32.Build.0 = Develop|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Profile|Win32.Build.0 = Profile|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|Win32.ActiveCfg = Release|Win32\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|Win32.Build.0 = Release|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|Win32.Build.0 = Debug|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Develop|Win32.Build.0 = Develop|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Profile|Win32.Build.0 = Profile|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|Win32.ActiveCfg = Release|Win32\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|Win32.Build.0 = Release|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|Win32.Build.0 = Debug|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Develop|Win32.Build.0 = Develop|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Profile|Win32.Build.0 = Profile|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|Win32.ActiveCfg = Release|Win32\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|Win32.Build.0 = Release|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|Win32.Build.0 = Debug|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Develop|Win32.Build.0 = Develop|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Profile|Win32.Build.0 = Profile|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|Win32.ActiveCfg = Release|Win32\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|Win32.Build.0 = Release|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|Win32.Build.0 = Debug|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Develop|Win32.Build.0 = Develop|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Profile|Win32.Build.0 = Profile|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|Win32.ActiveCfg = Release|Win32\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|Win32.Build.0 = Release|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|Win32.Build.0 = Debug|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Develop|Win32.Build.0 = Develop|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Profile|Win32.Build.0 = Profile|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|Win32.ActiveCfg = Release|Win32\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|Win32.Build.0 = Release|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|Win32.Build.0 = Debug|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Develop|Win32.Build.0 = Develop|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Profile|Win32.Build.0 = Profile|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|Win32.ActiveCfg = Release|Win32\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|Win32.Build.0 = Release|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Debug|Win32.Build.0 = Debug|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Develop|Win32.ActiveCfg = Develop|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Develop|Win32.Build.0 = Develop|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Profile|Win32.ActiveCfg = Profile|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Profile|Win32.Build.0 = Profile|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Release|Win32.ActiveCfg = Release|Win32\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Release|Win32.Build.0 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
+       EndGlobalSection\r
+       GlobalSection(NestedProjects) = preSolution\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/common/common.vcxproj b/common/common.vcxproj
new file mode 100644 (file)
index 0000000..9dbc3db
--- /dev/null
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{02308602-7FE0-4253-B96E-22134919F56A}</ProjectGuid>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <RootNamespace>common</RootNamespace>\r
+    <ProjectName>common</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>true</UseDebugLibraries>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <IncludePath>..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.6\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath>..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\;$(LibraryPath)</LibraryPath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <IncludePath>..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.6\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath>..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\;$(LibraryPath)</LibraryPath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <IncludePath>..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.6\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath>..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\;$(LibraryPath)</LibraryPath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <IncludePath>..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.6\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath>..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\;$(LibraryPath)</LibraryPath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <ClCompile>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <Optimization>Disabled</Optimization>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_DEBUG;SFML_DYNAMIC;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <SmallerTypeCheck>true</SmallerTypeCheck>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <ForcedIncludeFiles>compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+    </Link>\r
+    <PreBuildEvent>\r
+      <Command>"SubWCRev.exe" "$(SolutionDir)." "$(SolutionDir).\version.tmpl" "$(SolutionDir).\version.h"</Command>\r
+    </PreBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <FunctionLevelLinking>\r
+      </FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;SFML_DYNAMIC;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <ForcedIncludeFiles>compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <PreBuildEvent>\r
+      <Command>"SubWCRev.exe" "$(SolutionDir)." "$(SolutionDir).\version.tmpl" "$(SolutionDir).\version.h"</Command>\r
+    </PreBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <FunctionLevelLinking>\r
+      </FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;SFML_DYNAMIC;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <ForcedIncludeFiles>compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <PreBuildEvent>\r
+      <Command>"SubWCRev.exe" "$(SolutionDir)." "$(SolutionDir).\version.tmpl" "$(SolutionDir).\version.h"</Command>\r
+    </PreBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>Disabled</Optimization>\r
+      <FunctionLevelLinking>\r
+      </FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;SFML_DYNAMIC;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <PreBuildEvent>\r
+      <Command>"SubWCRev.exe" "$(SolutionDir)." "$(SolutionDir).\version.tmpl" "$(SolutionDir).\version.h"</Command>\r
+    </PreBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
+    <ClInclude Include="concurrency\com_context.h" />\r
+    <ClInclude Include="concurrency\executor.h" />\r
+    <ClInclude Include="concurrency\future_util.h" />\r
+    <ClInclude Include="concurrency\lock.h" />\r
+    <ClInclude Include="concurrency\target.h" />\r
+    <ClInclude Include="diagnostics\graph.h" />\r
+    <ClInclude Include="exception\exceptions.h" />\r
+    <ClInclude Include="exception\win32_exception.h" />\r
+    <ClInclude Include="filesystem\filesystem_monitor.h" />\r
+    <ClInclude Include="filesystem\polling_filesystem_monitor.h" />\r
+    <ClInclude Include="gl\gl_check.h" />\r
+    <ClInclude Include="log\log.h" />\r
+    <ClInclude Include="memory\memclr.h" />\r
+    <ClInclude Include="memory\memcpy.h" />\r
+    <ClInclude Include="memory\memshfl.h" />\r
+    <ClInclude Include="memory\page_locked_allocator.h" />\r
+    <ClInclude Include="memory\safe_ptr.h" />\r
+    <ClInclude Include="env.h" />\r
+    <ClInclude Include="os\windows\current_version.h" />\r
+    <ClInclude Include="os\windows\system_info.h" />\r
+    <ClInclude Include="stdafx.h" />\r
+    <ClInclude Include="utility\assert.h" />\r
+    <ClInclude Include="utility\move_on_copy.h" />\r
+    <ClInclude Include="utility\param.h" />\r
+    <ClInclude Include="utility\string.h" />\r
+    <ClInclude Include="utility\timer.h" />\r
+    <ClInclude Include="utility\tweener.h" />\r
+    <ClInclude Include="utility\utf8conv.h" />\r
+    <ClInclude Include="utility\utf8conv_inl.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="diagnostics\graph.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="exception\win32_exception.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="filesystem\polling_filesystem_monitor.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="gl\gl_check.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="log\log.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="env.cpp" />\r
+    <ClCompile Include="stdafx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="utility\string.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="utility\tweener.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/common/common.vcxproj.filters b/common/common.vcxproj.filters
new file mode 100644 (file)
index 0000000..ae7610c
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{bb2d04f1-2743-4d80-87a4-928970bb233a}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\os">\r
+      <UniqueIdentifier>{49ed2765-f23e-4a1b-9d6a-f80d510b92e1}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\os\windows">\r
+      <UniqueIdentifier>{1f3002ae-ebb8-4195-8cf3-1a5b87822f38}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\utility">\r
+      <UniqueIdentifier>{11860e2d-8adf-4573-956b-785e59aef2b0}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\memory">\r
+      <UniqueIdentifier>{9259676d-c225-4422-a50e-30d152d78dc2}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\log">\r
+      <UniqueIdentifier>{3b529e9b-c729-4c8a-8166-0cb8d8030973}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\gl">\r
+      <UniqueIdentifier>{0d94bbc2-e196-4618-a90b-19392a3a0a8e}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\exception">\r
+      <UniqueIdentifier>{35ca385e-c4db-4fe7-858b-0a0bb678675f}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\diagnostics">\r
+      <UniqueIdentifier>{29a29bcc-a9a0-4083-b713-c3773d18e177}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\concurrency">\r
+      <UniqueIdentifier>{644fe2e4-1199-4a0e-8d4c-63cf1ac82f1d}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\compiler">\r
+      <UniqueIdentifier>{63471750-a430-4167-9b49-31b7a068a913}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\compiler\vs">\r
+      <UniqueIdentifier>{28c25c8a-1277-4d2c-9e85-5af33f9938ea}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\filesystem">\r
+      <UniqueIdentifier>{bbca8bcd-702a-4fb7-827a-00b248fcc7f7}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="exception\win32_exception.cpp">\r
+      <Filter>source\exception</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="log\log.cpp">\r
+      <Filter>source\log</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\graph.cpp">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="stdafx.cpp" />\r
+    <ClCompile Include="utility\string.cpp">\r
+      <Filter>source\utility</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="gl\gl_check.cpp">\r
+      <Filter>source\gl</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="env.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="utility\tweener.cpp">\r
+      <Filter>source\utility</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="filesystem\polling_filesystem_monitor.cpp">\r
+      <Filter>source\filesystem</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="exception\exceptions.h">\r
+      <Filter>source\exception</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="exception\win32_exception.h">\r
+      <Filter>source\exception</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="compiler\vs\disable_silly_warnings.h">\r
+      <Filter>source\compiler\vs</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="concurrency\executor.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="log\log.h">\r
+      <Filter>source\log</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="gl\gl_check.h">\r
+      <Filter>source\gl</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="memory\page_locked_allocator.h">\r
+      <Filter>source\memory</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="memory\safe_ptr.h">\r
+      <Filter>source\memory</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="diagnostics\graph.h">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="stdafx.h" />\r
+    <ClInclude Include="utility\assert.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\string.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\timer.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\tweener.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="memory\memcpy.h">\r
+      <Filter>source\memory</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="memory\memclr.h">\r
+      <Filter>source\memory</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="os\windows\current_version.h">\r
+      <Filter>source\os\windows</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="os\windows\system_info.h">\r
+      <Filter>source\os\windows</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="concurrency\com_context.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="memory\memshfl.h">\r
+      <Filter>source\memory</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="env.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\move_on_copy.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="concurrency\target.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\param.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\utf8conv.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="utility\utf8conv_inl.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="concurrency\lock.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="concurrency\future_util.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="filesystem\filesystem_monitor.h">\r
+      <Filter>source\filesystem</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="filesystem\polling_filesystem_monitor.h">\r
+      <Filter>source\filesystem</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/common/common.vcxproj.user b/common/common.vcxproj.user
new file mode 100644 (file)
index 0000000..695b5c7
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+</Project>
\ No newline at end of file
diff --git a/common/compiler/vs/disable_silly_warnings.h b/common/compiler/vs/disable_silly_warnings.h
new file mode 100644 (file)
index 0000000..492b928
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#pragma once\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4100) // unreferenced formal parameter\r
+#pragma warning (disable : 4127) // conditional expression is constant\r
+#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored\r
+#pragma warning (disable : 4355) // 'this' : used in base member initializer list\r
+#pragma warning (disable : 4482) // nonstandard extension used: enum 'enum' used in qualified name\r
+#pragma warning (disable : 4503) // decorated name length exceeded, name was truncated\r
+#pragma warning (disable : 4512) // assignment operator could not be generated\r
+#pragma warning (disable : 4702) //  unreachable code\r
+#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#pragma warning (disable : 4505) //  unreferenced local function has been removed\r
+#pragma warning (disable : 4481) //  nonstandard extension used: override specifier 'override'\r
+#endif\r
+\r
diff --git a/common/concurrency/com_context.h b/common/concurrency/com_context.h
new file mode 100644 (file)
index 0000000..509c0af
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "executor.h"\r
+\r
+#include "../log/log.h"\r
+#include "../exception/exceptions.h"\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <Windows.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <functional>\r
+\r
+namespace caspar {\r
+\r
+template<typename T>\r
+class com_context : public executor\r
+{\r
+       std::unique_ptr<T> instance_;\r
+public:\r
+       com_context(const std::wstring& name) : executor(name)\r
+       {\r
+               executor::begin_invoke([]\r
+               {\r
+                       ::CoInitialize(nullptr);\r
+               });\r
+       }\r
+\r
+       ~com_context()\r
+       {\r
+               if(!executor::begin_invoke([&]\r
+               {\r
+                       instance_.reset(nullptr);\r
+                       ::CoUninitialize();\r
+               }).timed_wait(boost::posix_time::milliseconds(500)))\r
+               {\r
+                       CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources.";\r
+               }\r
+       }\r
+       \r
+       void reset(const std::function<T*()>& factory = nullptr)\r
+       {\r
+               executor::invoke([&]\r
+               {\r
+                       instance_.reset();\r
+                       if(factory)\r
+                               instance_.reset(factory());\r
+               });\r
+       }\r
+\r
+       T& operator*() const \r
+       {\r
+               if(instance_ == nullptr)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
+\r
+               return *instance_.get();\r
+       }  // noexcept\r
+\r
+       T* operator->() const \r
+       {\r
+               if(instance_ == nullptr)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
+               return instance_.get();\r
+       }  // noexcept\r
+\r
+       T* get() const\r
+       {\r
+               return instance_.get();\r
+       }  // noexcept\r
+\r
+       operator bool() const {return get() != nullptr;}\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/common/concurrency/executor.h b/common/concurrency/executor.h
new file mode 100644 (file)
index 0000000..79adf0a
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+* 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: Robert Nagy, ronag89@gmail.com
+*/
+
+#pragma once
+
+#include "../exception/win32_exception.h"
+#include "../exception/exceptions.h"
+#include "../utility/string.h"
+#include "../utility/move_on_copy.h"
+#include "../log/log.h"
+
+#include <tbb/atomic.h>
+#include <tbb/concurrent_queue.h>
+
+#include <boost/thread.hpp>
+#include <boost/optional.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <functional>
+
+namespace caspar {
+
+namespace detail {
+
+typedef struct tagTHREADNAME_INFO
+{
+       DWORD dwType; // must be 0x1000
+       LPCSTR szName; // pointer to name (in user addr space)
+       DWORD dwThreadID; // thread ID (-1=caller thread)
+       DWORD dwFlags; // reserved for future use, must be zero
+} THREADNAME_INFO;
+
+inline void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+{
+       THREADNAME_INFO info;
+       {
+               info.dwType = 0x1000;
+               info.szName = szThreadName;
+               info.dwThreadID = dwThreadID;
+               info.dwFlags = 0;
+       }
+       __try
+       {
+               RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
+       }
+       __except (EXCEPTION_CONTINUE_EXECUTION){}       
+}
+
+}
+
+enum task_priority
+{
+       high_priority,
+       normal_priority,
+       priority_count
+};
+
+enum thread_priority
+{
+       high_priority_class,
+       above_normal_priority_class,
+       normal_priority_class,
+       below_normal_priority_class
+};
+
+class executor : boost::noncopyable
+{
+       const std::string name_;
+       boost::thread thread_;
+       tbb::atomic<bool> is_running_;
+       tbb::atomic<bool> execute_rest_;
+       
+       typedef tbb::concurrent_bounded_queue<std::function<void()>> function_queue;
+       function_queue execution_queue_[priority_count];
+               
+       template<typename Func>
+       auto create_task(Func&& func) -> boost::packaged_task<decltype(func())> // noexcept
+       {       
+               typedef boost::packaged_task<decltype(func())> task_type;
+                               
+               auto task = task_type(std::forward<Func>(func));
+               
+               task.set_wait_callback(std::function<void(task_type&)>([=](task_type& my_task) // The std::function wrapper is required in order to add ::result_type to functor class.
+               {
+                       try
+                       {
+                               if(boost::this_thread::get_id() == thread_.get_id())  // Avoids potential deadlock.
+                                       my_task();
+                       }
+                       catch(boost::task_already_started&){}
+               }));
+                               
+               return std::move(task);
+       }
+
+public:
+               
+       explicit executor(const std::wstring& name) : name_(narrow(name)) // noexcept
+       {
+               is_running_ = true;
+               thread_ = boost::thread([this]{run();});
+       }
+       
+       virtual ~executor() // noexcept
+       {
+               stop();
+               join();
+       }
+
+       void set_capacity(size_t capacity) // noexcept
+       {
+               execution_queue_[normal_priority].set_capacity(capacity);
+       }
+
+       void set_priority_class(thread_priority p)
+       {
+               begin_invoke([=]
+               {
+                       if(p == high_priority_class)
+                               SetThreadPriority(GetCurrentThread(), HIGH_PRIORITY_CLASS);
+                       else if(p == above_normal_priority_class)
+                               SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);
+                       else if(p == normal_priority_class)
+                               SetThreadPriority(GetCurrentThread(), NORMAL_PRIORITY_CLASS);
+                       else if(p == below_normal_priority_class)
+                               SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);
+               });
+       }
+       
+       void clear()
+       {               
+               std::function<void()> func;
+               while(execution_queue_[normal_priority].try_pop(func));
+               while(execution_queue_[high_priority].try_pop(func));
+       }
+                               
+       void stop() // noexcept
+       {
+               execute_rest_ = false;
+               is_running_ = false;    
+               execution_queue_[normal_priority].try_push([]{}); // Wake the execution thread.
+       }
+                               
+       void stop_execute_rest() // noexcept
+       {
+               execute_rest_ = true;
+               is_running_ = false;
+               execution_queue_[normal_priority].try_push([]{}); // Wake the execution thread.
+       }
+
+       void wait() // noexcept
+       {
+               invoke([]{});
+       }
+
+       void join()
+       {
+               if(boost::this_thread::get_id() != thread_.get_id())
+                       thread_.join();
+       }
+
+       template<typename Func>
+       auto try_begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::optional<caspar::move_on_copy<boost::unique_future<decltype(func())>>>
+       {       
+               if(!is_running_)
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("executor not running."));
+
+               // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.
+               auto task_adaptor = make_move_on_copy(create_task(func));
+
+               auto future = task_adaptor.value.get_future();
+
+               // Enable the cancellation of the task if priority is other than
+               // normal, because there are two queues to try_push to. Either both
+               // succeed or nothing will be executed.
+               
+               boost::promise<bool> cancelled_promise;
+               boost::shared_future<bool> cancelled(cancelled_promise.get_future());
+
+               bool was_enqueued = execution_queue_[priority].try_push([=]() mutable
+               {
+                       // Wait until we know if we should cancel execution or not.
+                       if (cancelled.get())
+                               return;
+
+                       try
+                       {
+                               task_adaptor.value();
+                       }
+                       catch(boost::task_already_started&)
+                       {
+                       }
+                       catch(...)
+                       {
+                               CASPAR_LOG_CURRENT_EXCEPTION();
+                       }
+               });
+
+               if (!was_enqueued)
+                       return boost::optional<caspar::move_on_copy<boost::unique_future<decltype(func())>>>();
+
+               if (priority != normal_priority)
+               {
+                       was_enqueued = execution_queue_[normal_priority].try_push(nullptr);
+
+                       if (was_enqueued)
+                       {
+                               // Now we know that both enqueue operations has succeeded.
+                               cancelled_promise.set_value(false);
+                       }
+                       else
+                       {
+                               cancelled_promise.set_value(true); // The actual task has already been
+                                                                  // queued so we cancel it.
+
+                               return boost::optional<caspar::move_on_copy<boost::unique_future<decltype(func())>>>();
+                       }
+               }
+               else
+               {
+                       cancelled_promise.set_value(false);
+               }
+
+               return caspar::make_move_on_copy(std::move(future));
+       }
+                               
+       template<typename Func>
+       auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept
+       {       
+               if(!is_running_)
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("executor not running."));
+
+               // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.
+               auto task_adaptor = make_move_on_copy(create_task(func));
+
+               auto future = task_adaptor.value.get_future();
+
+               execution_queue_[priority].push([=]
+               {
+                       try
+                       {
+                               task_adaptor.value();
+                       }
+                       catch(boost::task_already_started&)
+                       {
+                       }
+                       catch(...)
+                       {
+                               CASPAR_LOG_CURRENT_EXCEPTION();
+                       }
+               });
+
+               if(priority != normal_priority)
+                       execution_queue_[normal_priority].push(nullptr);
+                                       
+               return std::move(future);               
+       }
+       
+       template<typename Func>
+       auto invoke(Func&& func, task_priority prioriy = normal_priority) -> decltype(func()) // noexcept
+       {
+               if(boost::this_thread::get_id() == thread_.get_id())  // Avoids potential deadlock.
+                       return func();
+               
+               return begin_invoke(std::forward<Func>(func), prioriy).get();
+       }
+       
+       void yield() // noexcept
+       {
+               if(boost::this_thread::get_id() != thread_.get_id())  // Only yield when calling from execution thread.
+                       return;
+
+               std::function<void()> func;
+               while(execution_queue_[high_priority].try_pop(func))
+               {
+                       if(func)
+                               func();
+               }       
+       }
+       
+       function_queue::size_type capacity() const /*noexcept*/ { return execution_queue_[normal_priority].capacity();  }
+       function_queue::size_type size() const /*noexcept*/ { return execution_queue_[normal_priority].size();  }
+       bool empty() const /*noexcept*/ { return execution_queue_[normal_priority].empty();     }
+       bool is_running() const /*noexcept*/ { return is_running_; }    
+               
+private:
+       
+       void execute() // noexcept
+       {
+               std::function<void()> func;
+               execution_queue_[normal_priority].pop(func);    
+
+               yield();
+
+               if(func)
+                       func();
+       }
+
+       void execute_rest(task_priority priority) // noexcept
+       {
+               std::function<void()> func;
+
+               while (execution_queue_[priority].try_pop(func))
+                       if (func)
+                               func();
+       }
+
+       void run() // noexcept
+       {
+               win32_exception::install_handler();             
+               detail::SetThreadName(GetCurrentThreadId(), name_.c_str());
+               while(is_running_)
+               {
+                       try
+                       {
+                               execute();
+                       }
+                       catch(...)
+                       {
+                               CASPAR_LOG_CURRENT_EXCEPTION();
+                       }
+               }
+
+               if (execute_rest_)
+               {
+                       execute_rest(high_priority);
+                       execute_rest(normal_priority);
+               }
+       }       
+};
+
+}
\ No newline at end of file
diff --git a/common/concurrency/future_util.h b/common/concurrency/future_util.h
new file mode 100644 (file)
index 0000000..952e96f
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+* 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 "../log/log.h"
+
+#include <boost/thread/future.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/function.hpp>
+#include <boost/optional.hpp>
+
+namespace caspar
+{
+
+/**
+ * A utility that helps the producer side of a future when the task is not
+ * able to complete immediately but there are known retry points in the code.
+ */
+template<class R>
+class retry_task
+{
+public:
+       typedef boost::function<boost::optional<R> ()> func_type;
+       
+       retry_task() : done_(false) {}
+
+       /**
+        * Reset the state with a new task. If the previous task has not completed
+        * the old one will be discarded.
+        *
+        * @param func The function that tries to calculate future result. If the
+        *             optional return value is set the future is marked as ready.
+        */
+       void set_task(const func_type& func)
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               func_ = func;
+               done_ = false;
+               promise_ = boost::promise<R>();
+       }
+
+       /**
+        * Take ownership of the future for the current task. Cannot only be called
+        * once for each task.
+        *
+        * @return the future.
+        */
+       boost::unique_future<R> get_future()
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               return promise_.get_future();
+       }
+
+       /**
+        * Call this when it is guaranteed or probable that the task will be able
+        * to complete.
+        *
+        * @return true if the task completed (the future will have a result).
+        */
+       bool try_completion()
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               return try_completion_internal();
+       }
+
+       /**
+        * Call this when it is certain that the result should be ready, and if not
+        * it should be regarded as an unrecoverable error (retrying again would
+        * be useless), so the future will be marked as failed.
+        *
+        * @param exception The exception to mark the future with *if* the task
+        *                  completion fails.
+        */
+       template <class E>
+       void try_or_fail(const E& exception)
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               if (!try_completion_internal())
+               {
+                       try
+                       {
+                               throw exception;
+                       }
+                       catch (...)
+                       {
+                               CASPAR_LOG_CURRENT_EXCEPTION();
+                               promise_.set_exception(boost::current_exception());
+                               done_ = true;
+                       }
+               }
+       }
+private:
+       bool try_completion_internal()
+       {
+               if (!func_)
+                       return false;
+
+               if (done_)
+                       return true;
+
+               boost::optional<R> result;
+
+               try
+               {
+                       result = func_();
+               }
+               catch (...)
+               {
+                       CASPAR_LOG_CURRENT_EXCEPTION();
+                       promise_.set_exception(boost::current_exception());
+                       done_ = true;
+
+                       return true;
+               }
+
+               if (result)
+               {
+                       promise_.set_value(*result);
+                       done_ = true;
+               }
+
+               return done_;
+       }
+private:
+       boost::mutex mutex_;
+       func_type func_;
+       boost::promise<R> promise_;
+       bool done_;
+};
+
+/**
+ * Wrap a value in a future with an already known result.
+ * <p>
+ * Useful when the result of an operation is already known at the time of
+ * calling.
+ *
+ * @param value The r-value to wrap.
+ *
+ * @return The future with the result set.
+ */
+template<class R>
+boost::unique_future<R> wrap_as_future(R&& value)
+{
+       boost::promise<R> p;
+
+       p.set_value(value);
+
+       return p.get_future();
+}
+
+}
diff --git a/common/concurrency/lock.h b/common/concurrency/lock.h
new file mode 100644 (file)
index 0000000..73316b2
--- /dev/null
@@ -0,0 +1,12 @@
+#pragma once\r
+\r
+namespace caspar {\r
+\r
+template<typename T, typename F>\r
+auto lock(T& mutex, F&& func) -> decltype(func())\r
+{\r
+       T::scoped_lock lock(mutex);\r
+       return func();\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/concurrency/target.h b/common/concurrency/target.h
new file mode 100644 (file)
index 0000000..8f5cadc
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar {\r
+\r
+template<typename T>\r
+struct target\r
+{\r
+       virtual void send(const T&) = 0;\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/common/diagnostics/graph.cpp b/common/diagnostics/graph.cpp
new file mode 100644 (file)
index 0000000..1df5577
--- /dev/null
@@ -0,0 +1,536 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "graph.h"\r
+\r
+#pragma warning (disable : 4244)\r
+\r
+#include "../concurrency/executor.h"\r
+#include "../concurrency/lock.h"\r
+#include "../env.h"\r
+\r
+#include <SFML/Graphics.hpp>\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/optional.hpp>\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/range/algorithm_ext/erase.hpp>\r
+\r
+#include <tbb/concurrent_unordered_map.h>\r
+#include <tbb/atomic.h>\r
+#include <tbb/spin_mutex.h>\r
+\r
+#include <array>\r
+#include <numeric>\r
+#include <tuple>\r
+\r
+namespace caspar { namespace diagnostics {\r
+               \r
+int color(float r, float g, float b, float a)\r
+{\r
+       int code = 0;\r
+       code |= static_cast<int>(r*255.0f+0.5f) << 24;\r
+       code |= static_cast<int>(g*255.0f+0.5f) << 16;\r
+       code |= static_cast<int>(b*255.0f+0.5f) <<  8;\r
+       code |= static_cast<int>(a*255.0f+0.5f) <<  0;\r
+       return code;\r
+}\r
+\r
+std::tuple<float, float, float, float> color(int code)\r
+{\r
+       float r = static_cast<float>((code >> 24) & 255)/255.0f;\r
+       float g = static_cast<float>((code >> 16) & 255)/255.0f;\r
+       float b = static_cast<float>((code >>  8) & 255)/255.0f;\r
+       float a = static_cast<float>((code >>  0) & 255)/255.0f;\r
+       return std::make_tuple(r, g, b, a);\r
+}\r
+\r
+struct drawable : public sf::Drawable\r
+{\r
+       virtual ~drawable(){}\r
+       virtual void render(sf::RenderTarget& target) = 0;\r
+       virtual void Render(sf::RenderTarget& target) const { const_cast<drawable*>(this)->render(target);}\r
+};\r
+\r
+class context : public drawable\r
+{      \r
+       std::unique_ptr<sf::RenderWindow> window_;\r
+       \r
+       std::list<std::weak_ptr<drawable>> drawables_;\r
+               \r
+       executor executor_;\r
+public:                                        \r
+\r
+       static void register_drawable(const std::shared_ptr<drawable>& drawable)\r
+       {\r
+               if(!drawable)\r
+                       return;\r
+\r
+               get_instance().executor_.begin_invoke([=]\r
+               {\r
+                       get_instance().do_register_drawable(drawable);\r
+               }, high_priority);\r
+       }\r
+\r
+       static void show(bool value)\r
+       {\r
+               get_instance().executor_.begin_invoke([=]\r
+               {       \r
+                       get_instance().do_show(value);\r
+               }, high_priority);\r
+       }\r
+                               \r
+private:\r
+       context() : executor_(L"diagnostics")\r
+       {\r
+               executor_.set_priority_class(below_normal_priority_class);\r
+       }\r
+\r
+       void do_show(bool value)\r
+       {\r
+               if(value)\r
+               {\r
+                       if(!window_)\r
+                       {\r
+                               window_.reset(new sf::RenderWindow(sf::VideoMode(750, 750), "CasparCG Diagnostics"));\r
+                               window_->SetPosition(0, 0);\r
+                               window_->SetActive();\r
+                               glEnable(GL_BLEND);\r
+                               glEnable(GL_LINE_SMOOTH);\r
+                               glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
+                               tick();\r
+                       }\r
+               }\r
+               else\r
+                       window_.reset();\r
+       }\r
+\r
+       void tick()\r
+       {\r
+               if(!window_)\r
+                       return;\r
+\r
+               sf::Event e;\r
+               while(window_->GetEvent(e))\r
+               {\r
+                       if(e.Type == sf::Event::Closed)\r
+                       {\r
+                               window_.reset();\r
+                               return;\r
+                       }\r
+               }               \r
+               glClear(GL_COLOR_BUFFER_BIT);\r
+               window_->Draw(*this);\r
+               window_->Display();\r
+               boost::this_thread::sleep(boost::posix_time::milliseconds(10));\r
+               executor_.begin_invoke([this]{tick();});\r
+       }\r
+\r
+       void render(sf::RenderTarget& target)\r
+       {\r
+               auto count = std::max<size_t>(8, drawables_.size());\r
+               float target_dy = 1.0f/static_cast<float>(count);\r
+\r
+               float last_y = 0.0f;\r
+               int n = 0;\r
+               for(auto it = drawables_.begin(); it != drawables_.end(); ++n)\r
+               {\r
+                       auto drawable = it->lock();\r
+                       if(drawable)\r
+                       {\r
+                               drawable->SetScale(static_cast<float>(window_->GetWidth()), static_cast<float>(target_dy*window_->GetHeight()));\r
+                               float target_y = std::max(last_y, static_cast<float>(n * window_->GetHeight())*target_dy);\r
+                               drawable->SetPosition(0.0f, target_y);                  \r
+                               target.Draw(*drawable);                         \r
+                               ++it;           \r
+                       }\r
+                       else    \r
+                               it = drawables_.erase(it);                      \r
+               }               \r
+       }       \r
+       \r
+       void do_register_drawable(const std::shared_ptr<drawable>& drawable)\r
+       {\r
+               drawables_.push_back(drawable);\r
+               auto it = drawables_.begin();\r
+               while(it != drawables_.end())\r
+               {\r
+                       if(it->lock())\r
+                               ++it;\r
+                       else    \r
+                               it = drawables_.erase(it);                      \r
+               }\r
+       }\r
+       \r
+       static context& get_instance()\r
+       {\r
+               static context impl;\r
+               return impl;\r
+       }\r
+};\r
+\r
+class line : public drawable\r
+{\r
+       boost::circular_buffer<std::pair<float, bool>> line_data_;\r
+\r
+       tbb::atomic<float>      tick_data_;\r
+       tbb::atomic<bool>       tick_tag_;\r
+       tbb::atomic<int>        color_;\r
+public:\r
+       line(size_t res = 1200)\r
+               : line_data_(res)\r
+       {\r
+               tick_data_      = -1.0f;\r
+               color_          = 0xFFFFFFFF;\r
+               tick_tag_       = false;\r
+\r
+               line_data_.push_back(std::make_pair(-1.0f, false));\r
+       }\r
+       \r
+       void set_value(float value)\r
+       {\r
+               tick_data_ = value;\r
+       }\r
+       \r
+       void set_tag()\r
+       {\r
+               tick_tag_ = true;\r
+       }\r
+               \r
+       void set_color(int color)\r
+       {\r
+               color_ = color;\r
+       }\r
+\r
+       int get_color()\r
+       {\r
+               return color_;\r
+       }\r
+               \r
+       void render(sf::RenderTarget& target)\r
+       {\r
+               float dx = 1.0f/static_cast<float>(line_data_.capacity());\r
+               float x = static_cast<float>(line_data_.capacity()-line_data_.size())*dx;\r
+\r
+               line_data_.push_back(std::make_pair(tick_data_, tick_tag_));            \r
+               tick_tag_   = false;\r
+                               \r
+               glBegin(GL_LINE_STRIP);\r
+               auto c = color(color_);\r
+               glColor4f(std::get<0>(c), std::get<1>(c), std::get<2>(c), 0.8f);                \r
+               for(size_t n = 0; n < line_data_.size(); ++n)           \r
+                       if(line_data_[n].first > -0.5)\r
+                               glVertex3d(x+n*dx, std::max(0.05, std::min(0.95, (1.0f-line_data_[n].first)*0.8 + 0.1f)), 0.0);         \r
+               glEnd();\r
+                               \r
+               glEnable(GL_LINE_STIPPLE);\r
+               glLineStipple(3, 0xAAAA);\r
+               for(size_t n = 0; n < line_data_.size(); ++n)   \r
+               {\r
+                       if(line_data_[n].second)\r
+                       {\r
+                               glBegin(GL_LINE_STRIP);                 \r
+                                       glVertex3f(x+n*dx, 0.0f, 0.0f);                         \r
+                                       glVertex3f(x+n*dx, 1.0f, 0.0f);         \r
+                               glEnd();\r
+                       }\r
+               }\r
+               glDisable(GL_LINE_STIPPLE);\r
+       }\r
+};\r
+\r
+struct graph::impl : public drawable\r
+{\r
+       tbb::concurrent_unordered_map<std::string, diagnostics::line> lines_;\r
+\r
+       tbb::spin_mutex mutex_;\r
+       std::wstring text_;\r
+       bool auto_reset_;\r
+\r
+       impl()\r
+       {\r
+       }\r
+               \r
+       void set_text(const std::wstring& value)\r
+       {\r
+               auto temp = value;\r
+               lock(mutex_, [&]\r
+               {\r
+                       text_ = std::move(temp);\r
+               });\r
+       }\r
+\r
+       void set_value(const std::string& name, double value)\r
+       {\r
+               lines_[name].set_value(value);\r
+       }\r
+\r
+       void set_tag(const std::string& name)\r
+       {\r
+               lines_[name].set_tag();\r
+       }\r
+\r
+       void set_color(const std::string& name, int color)\r
+       {\r
+               lines_[name].set_color(color);\r
+       }\r
+\r
+       void auto_reset()\r
+       {\r
+               lock(mutex_, [this]\r
+               {\r
+                       auto_reset_ = true;\r
+               });\r
+       }\r
+               \r
+private:\r
+       void render(sf::RenderTarget& target)\r
+       {\r
+               const size_t text_size = 15;\r
+               const size_t text_margin = 2;\r
+               const size_t text_offset = (text_size+text_margin*2)*2;\r
+\r
+               std::wstring text_str;\r
+               bool auto_reset;\r
+               {\r
+                       tbb::spin_mutex::scoped_lock lock(mutex_);\r
+                       text_str = text_;\r
+                       auto_reset = auto_reset_;\r
+               }\r
+\r
+               sf::String text(text_str.c_str(), sf::Font::GetDefaultFont(), text_size);\r
+               text.SetStyle(sf::String::Italic);\r
+               text.Move(text_margin, text_margin);\r
+               \r
+               glPushMatrix();\r
+                       glScaled(1.0f/GetScale().x, 1.0f/GetScale().y, 1.0f);\r
+                       target.Draw(text);\r
+                       float x_offset = text_margin;\r
+                       for(auto it = lines_.begin(); it != lines_.end(); ++it)\r
+                       {                                               \r
+                               sf::String line_text(it->first, sf::Font::GetDefaultFont(), text_size);\r
+                               line_text.SetPosition(x_offset, text_margin+text_offset/2);\r
+                               auto c = it->second.get_color();\r
+                               line_text.SetColor(sf::Color((c >> 24) & 255, (c >> 16) & 255, (c >> 8) & 255, (c >> 0) & 255));\r
+                               target.Draw(line_text);\r
+                               x_offset = line_text.GetRect().Right + text_margin*2;\r
+                       }\r
+\r
+                       glDisable(GL_TEXTURE_2D);\r
+               glPopMatrix();\r
+\r
+               glBegin(GL_QUADS);\r
+                       glColor4f(1.0f, 1.0f, 1.0f, 0.2f);      \r
+                       glVertex2f(1.0f, 0.99f);\r
+                       glVertex2f(0.0f, 0.99f);\r
+                       glVertex2f(0.0f, 0.01f);        \r
+                       glVertex2f(1.0f, 0.01f);        \r
+               glEnd();\r
+\r
+               glPushMatrix();\r
+                       glTranslated(0.0f, text_offset/GetScale().y, 1.0f);\r
+                       glScaled(1.0f, 1.0-text_offset/GetScale().y, 1.0f);\r
+               \r
+                       glEnable(GL_LINE_STIPPLE);\r
+                       glLineStipple(3, 0xAAAA);\r
+                       glColor4f(1.0f, 1.0f, 1.9f, 0.5f);      \r
+                       glBegin(GL_LINE_STRIP);         \r
+                               glVertex3f(0.0f, (1.0f-0.5f) * 0.8f + 0.1f, 0.0f);              \r
+                               glVertex3f(1.0f, (1.0f-0.5f) * 0.8f + 0.1f, 0.0f);      \r
+                       glEnd();\r
+                       glBegin(GL_LINE_STRIP);         \r
+                               glVertex3f(0.0f, (1.0f-0.0f) * 0.8f + 0.1f, 0.0f);              \r
+                               glVertex3f(1.0f, (1.0f-0.0f) * 0.8f + 0.1f, 0.0f);      \r
+                       glEnd();\r
+                       glBegin(GL_LINE_STRIP);         \r
+                               glVertex3f(0.0f, (1.0f-1.0f) * 0.8f + 0.1f, 0.0f);              \r
+                               glVertex3f(1.0f, (1.0f-1.0f) * 0.8f + 0.1f, 0.0f);      \r
+                       glEnd();\r
+                       glDisable(GL_LINE_STIPPLE);\r
+\r
+                       //target.Draw(diagnostics::guide(1.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
+                       //target.Draw(diagnostics::guide(0.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
+\r
+                       for(auto it = lines_.begin(); it != lines_.end(); ++it)\r
+                       {\r
+                               target.Draw(it->second);\r
+\r
+                               if (auto_reset)\r
+                                       it->second.set_value(0.0f);\r
+                       }\r
+               \r
+               glPopMatrix();\r
+       }\r
+\r
+       impl(impl&);\r
+       impl& operator=(impl&);\r
+};\r
+       \r
+graph::graph() : impl_(new impl())\r
+{\r
+}\r
+\r
+void graph::set_text(const std::wstring& value){impl_->set_text(value);}\r
+void graph::set_value(const std::string& name, double value){impl_->set_value(name, value);}\r
+void graph::set_color(const std::string& name, int color){impl_->set_color(name, color);}\r
+void graph::set_tag(const std::string& name){impl_->set_tag(name);}\r
+void graph::auto_reset(){impl_->auto_reset();}\r
+\r
+void register_graph(const safe_ptr<graph>& graph)\r
+{\r
+       context::register_drawable(graph->impl_);\r
+}\r
+\r
+void show_graphs(bool value)\r
+{\r
+       context::show(value);\r
+}\r
+\r
+//namespace v2\r
+//{    \r
+//     \r
+//struct line::impl\r
+//{\r
+//     std::wstring name_;\r
+//     boost::circular_buffer<data> ticks_;\r
+//\r
+//     impl(const std::wstring& name) \r
+//             : name_(name)\r
+//             , ticks_(1024){}\r
+//     \r
+//     void set_value(float value)\r
+//     {\r
+//             ticks_.push_back();\r
+//             ticks_.back().value = value;\r
+//     }\r
+//\r
+//     void set_value(float value)\r
+//     {\r
+//             ticks_.clear();\r
+//             set_value(value);\r
+//     }\r
+//};\r
+//\r
+//line::line(){}\r
+//line::line(const std::wstring& name) : impl_(new impl(name)){}\r
+//std::wstring line::print() const {return impl_->name_;}\r
+//void line::set_value(float value){impl_->set_value(value);}\r
+//void line::set_value(float value){impl_->set_value(value);}\r
+//boost::circular_buffer<data>& line::ticks() { return impl_->ticks_;}\r
+//\r
+//struct graph::impl\r
+//{\r
+//     std::map<std::wstring, line> lines_;\r
+//     color                                            color_;\r
+//     printer                                          printer_;\r
+//\r
+//     impl(const std::wstring& name) \r
+//             : printer_([=]{return name;}){}\r
+//\r
+//     impl(const printer& parent_printer) \r
+//             : printer_(parent_printer){}\r
+//     \r
+//     void set_value(const std::wstring& name, float value)\r
+//     {\r
+//             auto it = lines_.find(name);\r
+//             if(it == lines_.end())\r
+//                     it = lines_.insert(std::make_pair(name, line(name))).first;\r
+//\r
+//             it->second.set_value(value);\r
+//     }\r
+//\r
+//     void set_value(const std::wstring& name, float value)\r
+//     {\r
+//             auto it = lines_.find(name);\r
+//             if(it == lines_.end())\r
+//                     it = lines_.insert(std::make_pair(name, line(name))).first;\r
+//\r
+//             it->second.set_value(value);\r
+//     }\r
+//     \r
+//     void set_color(const std::wstring& name, color color)\r
+//     {\r
+//             color_ = color;\r
+//     }\r
+//\r
+//     std::map<std::wstring, line>& get_lines()\r
+//     {\r
+//             return lines_;\r
+//     }\r
+//     \r
+//     color get_color() const\r
+//     {\r
+//             return color_;\r
+//     }\r
+//\r
+//     std::wstring print() const\r
+//     {\r
+//             return printer_ ? printer_() : L"graph";\r
+//     }\r
+//};\r
+//     \r
+//graph::graph(const std::wstring& name) : impl_(new impl(name)){}\r
+//graph::graph(const printer& parent_printer) : impl_(new impl(parent_printer)){}\r
+//void graph::set_value(const std::wstring& name, float value){impl_->set_value(name, value);}\r
+//void graph::set_value(const std::wstring& name, float value){impl_->set_value(name, value);}\r
+//void graph::set_color(const std::wstring& name, color c){impl_->set_color(name, c);}\r
+//color graph::get_color() const {return impl_->get_color();}\r
+//std::wstring graph::print() const {return impl_->print();}\r
+//\r
+//safe_ptr<graph> graph::clone() const \r
+//{\r
+//     safe_ptr<graph> clone(new graph(std::wstring(L"")));\r
+//     clone->impl_->printer_ = impl_->printer_;\r
+//     clone->impl_->lines_ = impl_->lines_;\r
+//     clone->impl_->color_ = impl_->color_;   \r
+//}\r
+//\r
+//std::map<std::wstring, line>& graph::get_lines() {impl_->get_lines();}\r
+//\r
+//std::vector<safe_ptr<graph>> g_graphs;\r
+//\r
+//safe_ptr<graph> create_graph(const std::string& name)\r
+//{\r
+//     g_graphs.push_back(make_safe<graph>(name));\r
+//     return g_graphs.back();\r
+//}\r
+//\r
+//safe_ptr<graph> create_graph(const printer& parent_printer)\r
+//{\r
+//     g_graphs.push_back(make_safe<graph>(parent_printer));\r
+//     return g_graphs.back();\r
+//}\r
+//\r
+//static std::vector<safe_ptr<graph>> get_all_graphs()\r
+//{\r
+//     std::vector<safe_ptr<graph>> graphs;\r
+//     BOOST_FOREACH(auto& graph, g_graphs)\r
+//             graphs.push_back(graph->clone());\r
+//\r
+//     return graphs;\r
+//}\r
+//\r
+//}\r
+\r
+}}
\ No newline at end of file
diff --git a/common/diagnostics/graph.h b/common/diagnostics/graph.h
new file mode 100644 (file)
index 0000000..c64b271
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../memory/safe_ptr.h"\r
+\r
+#include <string>\r
+#include <tuple>\r
+\r
+namespace caspar { namespace diagnostics {\r
+       \r
+int color(float r, float g, float b, float a = 1.0f);\r
+std::tuple<float, float, float, float> color(int code);\r
+\r
+class graph\r
+{\r
+       friend void register_graph(const safe_ptr<graph>& graph);\r
+public:\r
+       graph();\r
+       void set_text(const std::wstring& value);\r
+       void set_value(const std::string& name, double value);\r
+       void set_color(const std::string& name, int color);\r
+       void set_tag(const std::string& name);\r
+       void auto_reset();\r
+private:\r
+       struct impl;\r
+       std::shared_ptr<impl> impl_;\r
+};\r
+\r
+void register_graph(const safe_ptr<graph>& graph);\r
+void show_graphs(bool value);\r
+\r
+}}
\ No newline at end of file
diff --git a/common/env.cpp b/common/env.cpp
new file mode 100644 (file)
index 0000000..c89cb34
--- /dev/null
@@ -0,0 +1,180 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"\r
+\r
+#include "env.h"\r
+\r
+#include "../version.h"\r
+\r
+#include "exception/exceptions.h"\r
+#include "log/log.h"\r
+#include "utility/string.h"\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/property_tree/xml_parser.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/thread/once.hpp>\r
+\r
+#include <functional>\r
+#include <iostream>\r
+\r
+namespace caspar { namespace env {\r
+\r
+using namespace boost::filesystem2;\r
+\r
+std::wstring media;\r
+std::wstring log;\r
+std::wstring ftemplate;\r
+std::wstring data;\r
+std::wstring thumbnails;\r
+boost::property_tree::wptree pt;\r
+\r
+void check_is_configured()\r
+{\r
+       if(pt.empty())\r
+               BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Enviroment properties has not been configured"));\r
+}\r
+\r
+void configure(const std::wstring& filename)\r
+{\r
+       try\r
+       {\r
+               auto initialPath = boost::filesystem::initial_path<boost::filesystem2::wpath>().file_string();\r
+       \r
+               std::wifstream file(initialPath + L"\\" + filename);\r
+               boost::property_tree::read_xml(file, pt, boost::property_tree::xml_parser::trim_whitespace | boost::property_tree::xml_parser::no_comments);\r
+\r
+               auto paths = pt.get_child(L"configuration.paths");\r
+               media = widen(paths.get(L"media-path", initialPath + L"\\media\\"));\r
+               log = widen(paths.get(L"log-path", initialPath + L"\\log\\"));\r
+               ftemplate = complete(wpath(widen(paths.get(L"template-path", initialPath + L"\\template\\")))).string();                \r
+               data = widen(paths.get(L"data-path", initialPath + L"\\data\\"));\r
+               thumbnails = widen(paths.get(L"thumbnails-path", initialPath + L"\\thumbnails\\"));\r
+\r
+               try\r
+               {\r
+                       for(auto it = boost::filesystem2::wdirectory_iterator(initialPath); it != boost::filesystem2::wdirectory_iterator(); ++it)\r
+                       {\r
+                               if(it->filename().find(L".fth") != std::wstring::npos)                  \r
+                               {\r
+                                       auto from_path = *it;\r
+                                       auto to_path = boost::filesystem2::wpath(ftemplate + L"/" + it->filename());\r
+                               \r
+                                       if(boost::filesystem2::exists(to_path))\r
+                                               boost::filesystem2::remove(to_path);\r
+\r
+                                       boost::filesystem2::copy_file(from_path, to_path);\r
+                               }       \r
+                       }\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       CASPAR_LOG(error) << L"Failed to copy template-hosts from initial-path to template-path.";\r
+               }\r
+       }\r
+       catch(...)\r
+       {\r
+               std::wcout << L" ### Invalid configuration file. ###";\r
+               throw;\r
+       }\r
+\r
+       try\r
+       {\r
+               auto media_path = boost::filesystem::wpath(media);\r
+               if(!boost::filesystem::exists(media_path))\r
+                       boost::filesystem::create_directory(media_path);\r
+               \r
+               auto log_path = boost::filesystem::wpath(log);\r
+               if(!boost::filesystem::exists(log_path))\r
+                       boost::filesystem::create_directory(log_path);\r
+               \r
+               auto template_path = boost::filesystem::wpath(ftemplate);\r
+               if(!boost::filesystem::exists(template_path))\r
+                       boost::filesystem::create_directory(template_path);\r
+               \r
+               auto data_path = boost::filesystem::wpath(data);\r
+               if(!boost::filesystem::exists(data_path))\r
+                       boost::filesystem::create_directory(data_path);\r
+               \r
+               auto thumbnails_path = boost::filesystem::wpath(thumbnails);\r
+               if(!boost::filesystem::exists(thumbnails_path))\r
+                       boost::filesystem::create_directory(thumbnails_path);\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               CASPAR_LOG(error) << L"Failed to create configured directories.";\r
+       }\r
+}\r
+       \r
+const std::wstring& media_folder()\r
+{\r
+       check_is_configured();\r
+       return media;\r
+}\r
+\r
+const std::wstring& log_folder()\r
+{\r
+       check_is_configured();\r
+       return log;\r
+}\r
+\r
+const std::wstring& template_folder()\r
+{\r
+       check_is_configured();\r
+       return ftemplate;\r
+}\r
+\r
+const std::wstring& data_folder()\r
+{\r
+       check_is_configured();\r
+       return data;\r
+}\r
+\r
+const std::wstring& thumbnails_folder()\r
+{\r
+       check_is_configured();\r
+       return thumbnails;\r
+}\r
+\r
+#define QUOTE(str) #str\r
+#define EXPAND_AND_QUOTE(str) QUOTE(str)\r
+\r
+const std::wstring& version()\r
+{\r
+       static std::wstring ver = widen(\r
+                       EXPAND_AND_QUOTE(CASPAR_GEN)    "." \r
+                       EXPAND_AND_QUOTE(CASPAR_MAYOR)  "." \r
+                       EXPAND_AND_QUOTE(CASPAR_MINOR)  "." \r
+                       EXPAND_AND_QUOTE(CASPAR_REV)    " " \r
+                       CASPAR_TAG);\r
+       return ver;\r
+}\r
+\r
+const boost::property_tree::wptree& properties()\r
+{\r
+       check_is_configured();\r
+       return pt;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/common/env.h b/common/env.h
new file mode 100644 (file)
index 0000000..de0c280
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace env {\r
+\r
+void configure(const std::wstring& filename);\r
+\r
+const std::wstring& media_folder();\r
+const std::wstring& log_folder();\r
+const std::wstring& template_folder();\r
+const std::wstring& data_folder();\r
+const std::wstring& thumbnails_folder();\r
+const std::wstring& version();\r
+\r
+const boost::property_tree::wptree& properties();\r
+\r
+} }
\ No newline at end of file
diff --git a/common/exception/exceptions.h b/common/exception/exceptions.h
new file mode 100644 (file)
index 0000000..2c89f14
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <exception>\r
+#include <boost/exception/all.hpp>\r
+#include <boost/exception/error_info.hpp>\r
+#include <boost/throw_exception.hpp>\r
+\r
+namespace caspar {\r
+\r
+typedef boost::error_info<struct tag_arg_name_info, std::string>               arg_name_info;\r
+typedef boost::error_info<struct tag_arg_value_info, std::string>              arg_value_info;\r
+typedef boost::error_info<struct tag_msg_info, std::string>                            msg_info;\r
+typedef boost::error_info<struct tag_errorstr, std::string>                            errorstr;\r
+typedef boost::error_info<struct tag_source_info, std::string>                 source_info;\r
+typedef boost::error_info<struct tag_line_info, size_t>                                        line_info;\r
+typedef boost::error_info<struct errinfo_nested_exception_, std::exception_ptr> errinfo_nested_exception;\r
+\r
+struct caspar_exception                        : virtual boost::exception, virtual std::exception \r
+{\r
+       caspar_exception(){}\r
+       explicit caspar_exception(const char* msg) : std::exception(msg) {}\r
+};\r
+\r
+struct io_error                                        : virtual caspar_exception {};\r
+struct directory_not_found             : virtual io_error {};\r
+struct file_not_found                  : virtual io_error {};\r
+struct file_read_error          : virtual io_error {};\r
+\r
+struct invalid_argument                        : virtual caspar_exception {};\r
+struct null_argument                   : virtual invalid_argument {};\r
+struct out_of_range                            : virtual invalid_argument {};\r
+struct bad_alloc                               : virtual caspar_exception {};\r
+\r
+struct invalid_operation               : virtual caspar_exception {};\r
+struct operation_failed                        : virtual caspar_exception {};\r
+struct timed_out                               : virtual caspar_exception {};\r
+\r
+struct not_supported                   : virtual caspar_exception {};\r
+struct not_implemented                 : virtual caspar_exception {};\r
+\r
+}\r
+\r
+namespace std\r
+{\r
+\r
+inline bool operator!=(const std::exception_ptr& lhs, const std::exception_ptr& rhs)\r
+{\r
+       return !(lhs == rhs);\r
+}\r
+\r
+inline bool operator!=(const std::exception_ptr& lhs, std::nullptr_t)\r
+{\r
+       return !(lhs == nullptr);\r
+}\r
+\r
+inline bool operator!=(std::nullptr_t, const std::exception_ptr& rhs)\r
+{\r
+       return !(nullptr == rhs);\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/exception/win32_exception.cpp b/common/exception/win32_exception.cpp
new file mode 100644 (file)
index 0000000..43af7c0
--- /dev/null
@@ -0,0 +1,76 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "win32_exception.h"\r
+\r
+#include "../log/log.h"\r
+\r
+namespace caspar {\r
+\r
+void win32_exception::install_handler() \r
+{\r
+//#ifndef _DEBUG\r
+       _set_se_translator(win32_exception::Handler);\r
+//#endif\r
+}\r
+\r
+void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo) {\r
+       switch(errorCode)\r
+       {\r
+       case EXCEPTION_ACCESS_VIOLATION:\r
+               throw win32_access_violation(*(pInfo->ExceptionRecord));\r
+               break;\r
+\r
+       default:\r
+               throw win32_exception(*(pInfo->ExceptionRecord));\r
+       }\r
+}\r
+\r
+win32_exception::win32_exception(const EXCEPTION_RECORD& info) : message_("Win32 exception"), location_(info.ExceptionAddress), errorCode_(info.ExceptionCode)\r
+{\r
+       switch(info.ExceptionCode)\r
+       {\r
+       case EXCEPTION_ACCESS_VIOLATION:\r
+               message_ = "Access violation";\r
+               break;\r
+       case EXCEPTION_FLT_DIVIDE_BY_ZERO:\r
+       case EXCEPTION_INT_DIVIDE_BY_ZERO:\r
+               message_ = "Divide by zero";\r
+               break;\r
+       }\r
+}\r
+\r
+win32_access_violation::win32_access_violation(const EXCEPTION_RECORD& info) : win32_exception(info), isWrite_(false), badAddress_(0) \r
+{\r
+       isWrite_ = info.ExceptionInformation[0] == 1;\r
+       badAddress_ = reinterpret_cast<win32_exception::address>(info.ExceptionInformation[1]);\r
+}\r
+\r
+const char* win32_access_violation::what() const\r
+{\r
+       sprintf_s<>(messageBuffer_, "Access violation at %p, trying to %s %p", location(), isWrite_?"write":"read", badAddress_);\r
+\r
+       return messageBuffer_;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/exception/win32_exception.h b/common/exception/win32_exception.h
new file mode 100644 (file)
index 0000000..37b818b
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "exceptions.h"\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <windows.h>\r
+\r
+namespace caspar {\r
+\r
+class win32_exception : public std::exception\r
+{\r
+public:\r
+       typedef const void* address;\r
+       static void install_handler();\r
+\r
+       address location() const { return location_; }\r
+       unsigned int error_code() const { return errorCode_; }\r
+       virtual const char* what() const { return message_;     }\r
+\r
+protected:\r
+       win32_exception(const EXCEPTION_RECORD& info);\r
+       static void Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo);\r
+\r
+private:\r
+       const char* message_;\r
+\r
+       address location_;\r
+       unsigned int errorCode_;\r
+};\r
+\r
+class win32_access_violation : public win32_exception\r
+{\r
+       mutable char messageBuffer_[256];\r
+\r
+public:\r
+       bool is_write() const { return isWrite_; }\r
+       address bad_address() const { return badAddress_;}\r
+       virtual const char* what() const;\r
+\r
+protected:\r
+       win32_access_violation(const EXCEPTION_RECORD& info);\r
+       friend void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo);\r
+\r
+private:\r
+       bool isWrite_;\r
+       address badAddress_;\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/common/filesystem/filesystem_monitor.h b/common/filesystem/filesystem_monitor.h
new file mode 100644 (file)
index 0000000..ad0834f
--- /dev/null
@@ -0,0 +1,129 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <functional>\r
+#include <set>\r
+\r
+#include <boost/filesystem.hpp>\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include "../memory/safe_ptr.h"\r
+\r
+namespace caspar {\r
+\r
+/**\r
+ * A handle to an active filesystem monitor. Will stop scanning when destroyed.\r
+ */\r
+class filesystem_monitor : boost::noncopyable\r
+{\r
+public:\r
+       typedef safe_ptr<filesystem_monitor> ptr;\r
+\r
+       virtual ~filesystem_monitor() {}\r
+\r
+       /**\r
+        * @return a future made available when the initially available files have been\r
+        *         processed.\r
+        */\r
+       virtual boost::unique_future<void> initial_files_processed() = 0;\r
+\r
+       /**\r
+        * Reemmit the already known files as MODIFIED events.\r
+        */\r
+       virtual void reemmit_all() = 0;\r
+\r
+       /**\r
+        * Reemmit a specific file as a MODIFIED event.\r
+        *\r
+        * @param file The file to reemmit.\r
+        */\r
+       virtual void reemmit(const boost::filesystem::wpath& file) = 0;\r
+};\r
+\r
+/**\r
+ * The possible filesystem events.\r
+ */\r
+enum filesystem_event\r
+{\r
+       CREATED = 1,\r
+       REMOVED = 2,\r
+       MODIFIED = 4,\r
+       // Only used for describing a bitmask where all events are wanted. Never used when calling a handler.\r
+       ALL = 7\r
+};\r
+\r
+/**\r
+ * Handles filesystem events.\r
+ * <p>\r
+ * Will always be called from the same thread each time it is called.\r
+ *\r
+ * @param event Can be CREATED, REMOVED or MODIFIED.\r
+ * @param file  The file affected.\r
+ */\r
+typedef std::function<void (filesystem_event event, const boost::filesystem::wpath& file)> filesystem_monitor_handler;\r
+\r
+/**\r
+ * Called when the initially available files has been found.\r
+ * <p>\r
+ * Will be called from the same thread as filesystem_monitor_handler is called.\r
+ *\r
+ * @param initial_files The files that were initially available.\r
+ */\r
+typedef std::function<void (const std::set<boost::filesystem::wpath>& initial_files)> initial_files_handler;\r
+\r
+/**\r
+ * Factory for creating filesystem monitors.\r
+ */\r
+class filesystem_monitor_factory : boost::noncopyable\r
+{\r
+public:\r
+       virtual ~filesystem_monitor_factory() {}\r
+\r
+       /**\r
+        * Create a new monitor.\r
+        *\r
+        * @param folder_to_watch         The folder to recursively watch.\r
+        * @param events_of_interest_mask A bitmask of the events to prenumerate on.\r
+        * @param report_already_existing Whether to initially report all files in\r
+        *                                the folder as CREATED or to only care\r
+        *                                about changes.\r
+        * @param handler                 The handler to call each time a change is\r
+        *                                detected (only events defined by\r
+        *                                events_of_interest_mask).\r
+        * @param initial_files_handler   The optional handler to call when the\r
+        *                                initially available files has been\r
+        *                                discovered.\r
+        *\r
+        * @return The filesystem monitor handle.\r
+        */\r
+       virtual filesystem_monitor::ptr create(\r
+                       const boost::filesystem::wpath& folder_to_watch,\r
+                       filesystem_event events_of_interest_mask,\r
+                       bool report_already_existing,\r
+                       const filesystem_monitor_handler& handler,\r
+                       const initial_files_handler& initial_files_handler =\r
+                                       [] (const std::set<boost::filesystem::wpath>&) { }) = 0;\r
+};\r
+\r
+}\r
diff --git a/common/filesystem/polling_filesystem_monitor.cpp b/common/filesystem/polling_filesystem_monitor.cpp
new file mode 100644 (file)
index 0000000..20b78a8
--- /dev/null
@@ -0,0 +1,335 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "polling_filesystem_monitor.h"\r
+\r
+#include <map>\r
+#include <set>\r
+#include <iostream>\r
+\r
+#include <boost/thread.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/adaptor/map.hpp>\r
+#include <boost/range/algorithm/copy.hpp>\r
+#include <boost/filesystem/fstream.hpp>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include "../concurrency/executor.h"\r
+\r
+namespace caspar {\r
+\r
+class exception_protected_handler\r
+{\r
+       filesystem_monitor_handler handler_;\r
+public:\r
+       exception_protected_handler(const filesystem_monitor_handler& handler)\r
+               : handler_(handler)\r
+       {\r
+       }\r
+\r
+       void operator()(filesystem_event event, const boost::filesystem::wpath& file)\r
+       {\r
+               try\r
+               {\r
+                       boost::this_thread::interruption_point();\r
+                       handler_(event, file);\r
+                       boost::this_thread::interruption_point();\r
+               }\r
+               catch (const boost::thread_interrupted&)\r
+               {\r
+                       throw;\r
+               }\r
+               catch (...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+};\r
+\r
+class directory_monitor\r
+{\r
+       bool report_already_existing_;\r
+       boost::filesystem::wpath folder_;\r
+       filesystem_event events_mask_;\r
+       filesystem_monitor_handler handler_;\r
+       initial_files_handler initial_files_handler_;\r
+       bool first_scan_;\r
+       std::map<boost::filesystem::wpath, std::time_t> files_;\r
+       std::map<boost::filesystem::wpath, uintmax_t> being_written_sizes_;\r
+public:\r
+       directory_monitor(\r
+                       bool report_already_existing,\r
+                       const boost::filesystem::wpath& folder,\r
+                       filesystem_event events_mask,\r
+                       const filesystem_monitor_handler& handler,\r
+                       const initial_files_handler& initial_files_handler)\r
+               : report_already_existing_(report_already_existing)\r
+               , folder_(folder)\r
+               , events_mask_(events_mask)\r
+               , handler_(exception_protected_handler(handler))\r
+               , initial_files_handler_(initial_files_handler)\r
+               , first_scan_(true)\r
+       {\r
+       }\r
+\r
+       void reemmit_all()\r
+       {\r
+               if ((events_mask_ & MODIFIED) == 0)\r
+                       return;\r
+\r
+               BOOST_FOREACH(auto& file, files_)\r
+                       handler_(MODIFIED, file.first);\r
+       }\r
+\r
+       void reemmit(const boost::filesystem::wpath& file)\r
+       {\r
+               if ((events_mask_ & MODIFIED) == 0)\r
+                       return;\r
+\r
+               if (files_.find(file) != files_.end() && boost::filesystem::exists(file))\r
+                       handler_(MODIFIED, file);\r
+       }\r
+\r
+       void scan(const boost::function<bool ()>& should_abort)\r
+       {\r
+               static const std::time_t NO_LONGER_WRITING_AGE = 3; // Assume std::time_t is expressed in seconds\r
+               using namespace boost::filesystem;\r
+\r
+               bool interested_in_removed = (events_mask_ & REMOVED) > 0;\r
+               bool interested_in_created = (events_mask_ & CREATED) > 0;\r
+               bool interested_in_modified = (events_mask_ & MODIFIED) > 0;\r
+\r
+               std::set<wpath> removed_files;\r
+               boost::copy(\r
+                               files_ | boost::adaptors::map_keys,\r
+                               std::insert_iterator<decltype(removed_files)>(removed_files, removed_files.end()));\r
+\r
+               std::set<wpath> initial_files;\r
+\r
+               for (wrecursive_directory_iterator iter(folder_); iter != wrecursive_directory_iterator(); ++iter)\r
+               {\r
+                       if (should_abort())\r
+                               return;\r
+\r
+                       auto& path = iter->path();\r
+\r
+                       if (is_directory(path))\r
+                               continue;\r
+\r
+                       auto now = std::time(nullptr);\r
+                       std::time_t current_mtime;\r
+                       \r
+                       try\r
+                       {\r
+                               current_mtime = last_write_time(path);\r
+                       }\r
+                       catch (...)\r
+                       {\r
+                               // Probably removed, will be captured the next round.\r
+                               continue;\r
+                       }\r
+\r
+                       auto time_since_written_to = now - current_mtime;\r
+                       bool no_longer_being_written_to = time_since_written_to >= NO_LONGER_WRITING_AGE;\r
+                       auto previous_it = files_.find(path);\r
+                       bool already_known = previous_it != files_.end();\r
+\r
+                       if (already_known && no_longer_being_written_to)\r
+                       {\r
+                               bool modified = previous_it->second != current_mtime;\r
+\r
+                               if (modified && can_read_file(path))\r
+                               {\r
+                                       if (interested_in_modified)\r
+                                               handler_(MODIFIED, path);\r
+\r
+                                       files_[path] = current_mtime;\r
+                                       being_written_sizes_.erase(path);\r
+                               }\r
+                       }\r
+                       else if (no_longer_being_written_to && can_read_file(path))\r
+                       {\r
+                               if (interested_in_created && (report_already_existing_ || !first_scan_))\r
+                                       handler_(CREATED, path);\r
+\r
+                               if (first_scan_)\r
+                                       initial_files.insert(path);\r
+\r
+                               files_.insert(std::make_pair(path, current_mtime));\r
+                               being_written_sizes_.erase(path);\r
+                       }\r
+\r
+                       removed_files.erase(path);\r
+               }\r
+\r
+               BOOST_FOREACH(auto& path, removed_files)\r
+               {\r
+                       files_.erase(path);\r
+                       being_written_sizes_.erase(path);\r
+\r
+                       if (interested_in_removed)\r
+                               handler_(REMOVED, path);\r
+               }\r
+\r
+               if (first_scan_)\r
+                       initial_files_handler_(initial_files);\r
+\r
+               first_scan_ = false;\r
+       }\r
+private:\r
+       bool can_read_file(const boost::filesystem::wpath& file)\r
+       {\r
+               boost::filesystem::wifstream stream(file);\r
+\r
+               return stream.is_open();\r
+       }\r
+};\r
+\r
+class polling_filesystem_monitor : public filesystem_monitor\r
+{\r
+       directory_monitor root_monitor_;\r
+       boost::thread scanning_thread_;\r
+       tbb::atomic<bool> running_;\r
+       int scan_interval_millis_;\r
+       boost::promise<void> initial_scan_completion_;\r
+       tbb::concurrent_queue<boost::filesystem::wpath> to_reemmit_;\r
+       tbb::atomic<bool> reemmit_all_;\r
+public:\r
+       polling_filesystem_monitor(\r
+                       const boost::filesystem::wpath& folder_to_watch,\r
+                       filesystem_event events_of_interest_mask,\r
+                       bool report_already_existing,\r
+                       int scan_interval_millis,\r
+                       const filesystem_monitor_handler& handler,\r
+                       const initial_files_handler& initial_files_handler)\r
+               : root_monitor_(report_already_existing, folder_to_watch, events_of_interest_mask, handler, initial_files_handler)\r
+               , scan_interval_millis_(scan_interval_millis)\r
+       {\r
+               running_ = true;\r
+               reemmit_all_ = false;\r
+               scanning_thread_ = boost::thread([this] { scanner(); });\r
+       }\r
+\r
+       virtual ~polling_filesystem_monitor()\r
+       {\r
+               running_ = false;\r
+               scanning_thread_.interrupt();\r
+               scanning_thread_.join();\r
+       }\r
+\r
+       virtual boost::unique_future<void> initial_files_processed()\r
+       {\r
+               return initial_scan_completion_.get_future();\r
+       }\r
+\r
+       virtual void reemmit_all()\r
+       {\r
+               reemmit_all_ = true;\r
+       }\r
+\r
+       virtual void reemmit(const boost::filesystem::wpath& file)\r
+       {\r
+               to_reemmit_.push(file);\r
+       }\r
+private:\r
+       void scanner()\r
+       {\r
+               win32_exception::install_handler();\r
+               detail::SetThreadName(GetCurrentThreadId(), "polling_filesystem_monitor");\r
+\r
+               bool running = scan(false);\r
+               initial_scan_completion_.set_value();\r
+\r
+               if (running)\r
+                       while (scan(true));\r
+       }\r
+\r
+       bool scan(bool sleep)\r
+       {\r
+               try\r
+               {\r
+                       if (sleep)\r
+                               boost::this_thread::sleep(boost::posix_time::milliseconds(scan_interval_millis_));\r
+\r
+                       if (reemmit_all_.fetch_and_store(false))\r
+                               root_monitor_.reemmit_all();\r
+                       else\r
+                       {\r
+                               boost::filesystem::wpath file;\r
+\r
+                               while (to_reemmit_.try_pop(file))\r
+                                       root_monitor_.reemmit(file);\r
+                       }\r
+\r
+                       root_monitor_.scan([=] { return !running_; });\r
+               }\r
+               catch (const boost::thread_interrupted&)\r
+               {\r
+               }\r
+               catch (...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+\r
+               return running_;\r
+       }\r
+};\r
+\r
+struct polling_filesystem_monitor_factory::implementation\r
+{\r
+       int scan_interval_millis;\r
+\r
+       implementation(int scan_interval_millis)\r
+               : scan_interval_millis(scan_interval_millis)\r
+       {\r
+       }\r
+};\r
+\r
+polling_filesystem_monitor_factory::polling_filesystem_monitor_factory(int scan_interval_millis)\r
+       : impl_(new implementation(scan_interval_millis))\r
+{\r
+}\r
+\r
+polling_filesystem_monitor_factory::~polling_filesystem_monitor_factory()\r
+{\r
+}\r
+\r
+filesystem_monitor::ptr polling_filesystem_monitor_factory::create(\r
+               const boost::filesystem::wpath& folder_to_watch,\r
+               filesystem_event events_of_interest_mask,\r
+               bool report_already_existing,\r
+               const filesystem_monitor_handler& handler,\r
+               const initial_files_handler& initial_files_handler)\r
+{\r
+       return make_safe<polling_filesystem_monitor>(\r
+                       folder_to_watch,\r
+                       events_of_interest_mask,\r
+                       report_already_existing,\r
+                       impl_->scan_interval_millis,\r
+                       handler,\r
+                       initial_files_handler);\r
+}\r
+\r
+}\r
diff --git a/common/filesystem/polling_filesystem_monitor.h b/common/filesystem/polling_filesystem_monitor.h
new file mode 100644 (file)
index 0000000..d3b6701
--- /dev/null
@@ -0,0 +1,58 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "filesystem_monitor.h"\r
+\r
+namespace caspar {\r
+\r
+/**\r
+ * A portable filesystem monitor implementation which periodically polls the\r
+ * filesystem for changes. Will not react instantly but never misses any\r
+ * changes.\r
+ * <p>\r
+ * Will create a dedicated thread for each monitor created.\r
+ */\r
+class polling_filesystem_monitor_factory : public filesystem_monitor_factory\r
+{\r
+public:\r
+       /**\r
+        * Constructor.\r
+        *\r
+        * @param scan_interval_millis The number of milliseconds between each\r
+        *                             scheduled scan. Lower values lowers the reaction\r
+        *                             time but causes more I/O.\r
+        */\r
+       polling_filesystem_monitor_factory(int scan_interval_millis = 5000);\r
+       virtual ~polling_filesystem_monitor_factory();\r
+       virtual filesystem_monitor::ptr create(\r
+                       const boost::filesystem::wpath& folder_to_watch,\r
+                       filesystem_event events_of_interest_mask,\r
+                       bool report_already_existing,\r
+                       const filesystem_monitor_handler& handler,\r
+                       const initial_files_handler& initial_files_handler);\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}\r
diff --git a/common/gl/gl_check.cpp b/common/gl/gl_check.cpp
new file mode 100644 (file)
index 0000000..3619720
--- /dev/null
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////\r
+//\r
+// SFML - Simple and Fast Multimedia Library\r
+// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\r
+//\r
+// This software is provided 'as-is', without any express or implied warranty.\r
+// In no event will the authors be held liable for any damages arising from the use of this software.\r
+//\r
+// Permission is granted to anyone to use this software for any purpose,\r
+// including commercial applications, and to alter it and redistribute it freely,\r
+// subject to the following restrictions:\r
+//\r
+// 1. The origin of this software must not be misrepresented;\r
+//    you must not claim that you wrote the original software.\r
+//    If you use this software in a product, an acknowledgment\r
+//    in the product documentation would be appreciated but is not required.\r
+//\r
+// 2. Altered source versions must be plainly marked as such,\r
+//    and must not be misrepresented as being the original software.\r
+//\r
+// 3. This notice may not be removed or altered from any source distribution.\r
+//\r
+////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "gl_check.h"\r
+\r
+#include <GL/glew.h>\r
+\r
+#include "../exception/exceptions.h"\r
+#include "../log/log.h"\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace gl {      \r
+\r
+void SMFL_GLCheckError(const std::string& expr, const std::string& file, unsigned int line)\r
+{\r
+       // Get the last error\r
+       GLenum LastErrorCode = GL_NO_ERROR;\r
+\r
+       for(GLenum ErrorCode = glGetError(); ErrorCode != GL_NO_ERROR; ErrorCode = glGetError())\r
+       {\r
+               CASPAR_LOG(error) << "OpenGL Error: " << ErrorCode << L" " << glewGetErrorString(ErrorCode);\r
+               LastErrorCode = ErrorCode;\r
+       }\r
+\r
+       if (LastErrorCode != GL_NO_ERROR)\r
+       {\r
+               // Decode the error code\r
+               switch (LastErrorCode)\r
+               {\r
+                       case GL_INVALID_ENUM :\r
+                               BOOST_THROW_EXCEPTION(ogl_invalid_enum()\r
+                                       << msg_info("an unacceptable value has been specified for an enumerated argument")\r
+                                       << errorstr("GL_INVALID_ENUM")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_INVALID_VALUE :\r
+                               BOOST_THROW_EXCEPTION(ogl_invalid_value()\r
+                                       << msg_info("a numeric argument is out of range")\r
+                                       << errorstr("GL_INVALID_VALUE")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_INVALID_OPERATION :\r
+                               BOOST_THROW_EXCEPTION(ogl_invalid_operation()\r
+                                       << msg_info("the specified operation is not allowed in the current state")\r
+                                       << errorstr("GL_INVALID_OPERATION")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_STACK_OVERFLOW :\r
+                               BOOST_THROW_EXCEPTION(ogl_stack_overflow()\r
+                                       << msg_info("this command would cause a stack overflow")\r
+                                       << errorstr("GL_STACK_OVERFLOW")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_STACK_UNDERFLOW :\r
+                               BOOST_THROW_EXCEPTION(ogl_stack_underflow()\r
+                                       << msg_info("this command would cause a stack underflow")\r
+                                       << errorstr("GL_STACK_UNDERFLOW")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_OUT_OF_MEMORY :\r
+                               BOOST_THROW_EXCEPTION(ogl_out_of_memory()\r
+                                       << msg_info("there is not enough memory left to execute the command")\r
+                                       << errorstr("GL_OUT_OF_MEMORY")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+\r
+                       case GL_INVALID_FRAMEBUFFER_OPERATION :\r
+                               BOOST_THROW_EXCEPTION(ogl_stack_underflow()\r
+                                       << msg_info("the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"")\r
+                                       << errorstr("GL_INVALID_FRAMEBUFFER_OPERATION")\r
+                                       << line_info(line)\r
+                                       << source_info(file));\r
+               }\r
+       }\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/common/gl/gl_check.h b/common/gl/gl_check.h
new file mode 100644 (file)
index 0000000..926ac99
--- /dev/null
@@ -0,0 +1,64 @@
+////////////////////////////////////////////////////////////\r
+//\r
+// SFML - Simple and Fast Multimedia Library\r
+// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\r
+//\r
+// This software is provided 'as-is', without any express or implied warranty.\r
+// In no event will the authors be held liable for any damages arising from the use of this software.\r
+//\r
+// Permission is granted to anyone to use this software for any purpose,\r
+// including commercial applications, and to alter it and redistribute it freely,\r
+// subject to the following restrictions:\r
+//\r
+// 1. The origin of this software must not be misrepresented;\r
+//    you must not claim that you wrote the original software.\r
+//    If you use this software in a product, an acknowledgment\r
+//    in the product documentation would be appreciated but is not required.\r
+//\r
+// 2. Altered source versions must be plainly marked as such,\r
+//    and must not be misrepresented as being the original software.\r
+//\r
+// 3. This notice may not be removed or altered from any source distribution.\r
+//\r
+////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "../exception/exceptions.h"\r
+\r
+namespace caspar { namespace gl {\r
+\r
+struct ogl_exception                                                   : virtual caspar_exception{};\r
+struct ogl_invalid_enum                                                        : virtual ogl_exception{};\r
+struct ogl_invalid_value                                               : virtual ogl_exception{};\r
+struct ogl_invalid_operation                                   : virtual ogl_exception{};\r
+struct ogl_stack_overflow                                              : virtual ogl_exception{};\r
+struct ogl_stack_underflow                                             : virtual ogl_exception{};                      \r
+struct ogl_out_of_memory                                               : virtual ogl_exception{};\r
+struct ogl_invalid_framebuffer_operation_ext   : virtual ogl_exception{};\r
+\r
+void SMFL_GLCheckError(const std::string& expr, const std::string& File, unsigned int Line);\r
+\r
+//#ifdef _DEBUG\r
+       \r
+#define CASPAR_GL_EXPR_STR(expr) #expr\r
+\r
+#define GL(expr) \\r
+       if(false){}else \\r
+       { \\r
+               (expr);  \\r
+               caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\\r
+       }\r
+\r
+#define GL2(expr) \\r
+       [&]() -> decltype(expr)\\r
+       {\\r
+               auto ret = (expr); \\r
+               caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\\r
+               return ret;\\r
+       }()\r
+//#else\r
+//#define GL(expr) expr\r
+//#endif\r
+\r
+}}
\ No newline at end of file
diff --git a/common/log/log.cpp b/common/log/log.cpp
new file mode 100644 (file)
index 0000000..5051d09
--- /dev/null
@@ -0,0 +1,210 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4100) // 'identifier' : unreferenced formal parameter\r
+#pragma warning (disable : 4512) // 'class' : assignment operator could not be generated\r
+#endif\r
+\r
+#include "log.h"\r
+\r
+#include "../exception/exceptions.h"\r
+#include "../utility/string.h"\r
+#include <ios>\r
+#include <iomanip>\r
+#include <string>\r
+#include <ostream>\r
+\r
+#include <boost/shared_ptr.hpp>\r
+#include <boost/make_shared.hpp>\r
+#include <boost/filesystem/convenience.hpp>\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+\r
+#include <boost/log/core/core.hpp>\r
+\r
+#include <boost/log/formatters/stream.hpp>\r
+#include <boost/log/formatters/attr.hpp>\r
+#include <boost/log/formatters/date_time.hpp>\r
+#include <boost/log/formatters/message.hpp>\r
+\r
+#include <boost/log/filters/attr.hpp>\r
+\r
+#include <boost/log/sinks/text_file_backend.hpp>\r
+\r
+#include <boost/log/detail/universal_path.hpp>\r
+\r
+#include <boost/log/sinks/text_file_backend.hpp>\r
+#include <boost/log/sinks/text_ostream_backend.hpp>\r
+#include <boost/log/sinks/sync_frontend.hpp>\r
+#include <boost/log/sinks/async_frontend.hpp>\r
+#include <boost/log/core/record.hpp>\r
+#include <boost/log/utility/attribute_value_extractor.hpp>\r
+\r
+#include <boost/log/utility/init/common_attributes.hpp>\r
+#include <boost/log/utility/empty_deleter.hpp>\r
+#include <boost/lambda/lambda.hpp>\r
+#include <boost/bind.hpp>\r
+\r
+namespace caspar { namespace log {\r
+\r
+using namespace boost;\r
+\r
+void append_timestamp(std::wostream& stream)\r
+{\r
+       auto timestamp = boost::posix_time::microsec_clock::local_time();\r
+       auto date = timestamp.date();\r
+       auto time = timestamp.time_of_day();\r
+       auto milliseconds = time.fractional_seconds() / 1000; // microseconds to milliseconds\r
+\r
+       std::wstringstream buffer;\r
+\r
+       buffer\r
+               << std::setfill(L'0')\r
+               << L"["\r
+               << std::setw(4) << date.year() << L"-" << std::setw(2) << date.month().as_number() << "-" << std::setw(2) << date.day().as_number()\r
+               << L" "\r
+               << std::setw(2) << time.hours() << L":" << std::setw(2) << time.minutes() << L":" << std::setw(2) << time.seconds()\r
+               << L"."\r
+               << std::setw(3) << milliseconds\r
+               << L"] ";\r
+\r
+       stream << buffer.str();\r
+}\r
+\r
+void my_formatter(bool print_all_characters, std::wostream& strm, boost::log::basic_record<wchar_t> const& rec)\r
+{\r
+    namespace lambda = boost::lambda;\r
+       \r
+       #pragma warning(disable : 4996)\r
+\r
+       append_timestamp(strm);\r
+               \r
+    boost::log::attributes::current_thread_id::held_type thread_id;\r
+    if(boost::log::extract<boost::log::attributes::current_thread_id::held_type>(L"ThreadID", rec.attribute_values(), lambda::var(thread_id) = lambda::_1))\r
+        strm << L"[" << thread_id << L"] ";\r
+\r
+\r
+    severity_level severity;\r
+    if(boost::log::extract<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get(), rec.attribute_values(), lambda::var(severity) = lambda::_1))\r
+       {\r
+               std::stringstream ss;\r
+               ss << severity;\r
+        strm << L"[" << severity << L"] ";\r
+               for(int n = 0; n < 7-static_cast<int>(ss.str().size()); ++n)\r
+                       strm << L" ";\r
+       }\r
+\r
+       if (print_all_characters)\r
+       {\r
+               strm << rec.message();\r
+       }\r
+       else\r
+       {\r
+           strm << replace_nonprintable_copy(rec.message(), L'?');\r
+       }\r
+}\r
+\r
+namespace internal{\r
+       \r
+void init()\r
+{      \r
+       boost::log::add_common_attributes<wchar_t>();\r
+       typedef boost::log::aux::add_common_attributes_constants<wchar_t> traits_t;\r
+\r
+       typedef boost::log::sinks::synchronous_sink<boost::log::sinks::wtext_file_backend> file_sink_type;\r
+\r
+       typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::wtext_ostream_backend> stream_sink_type;\r
+\r
+       auto stream_backend = boost::make_shared<boost::log::sinks::wtext_ostream_backend>();\r
+       stream_backend->add_stream(boost::shared_ptr<std::wostream>(&std::wcout, boost::log::empty_deleter()));\r
+       stream_backend->auto_flush(true);\r
+\r
+       auto stream_sink = boost::make_shared<stream_sink_type>(stream_backend);\r
+       \r
+//#ifdef NDEBUG\r
+//     stream_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
+//#else\r
+//     stream_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
+//#endif\r
+\r
+       stream_sink->locked_backend()->set_formatter(boost::bind(my_formatter, false, _1, _2));\r
+\r
+       boost::log::wcore::get()->add_sink(stream_sink);\r
+}\r
+\r
+}\r
+\r
+void add_file_sink(const std::wstring& folder)\r
+{      \r
+       boost::log::add_common_attributes<wchar_t>();\r
+       typedef boost::log::aux::add_common_attributes_constants<wchar_t> traits_t;\r
+\r
+       typedef boost::log::sinks::synchronous_sink<boost::log::sinks::wtext_file_backend> file_sink_type;\r
+\r
+       try\r
+       {\r
+               if(!boost::filesystem::is_directory(folder))\r
+                       BOOST_THROW_EXCEPTION(directory_not_found());\r
+\r
+               auto file_sink = boost::make_shared<file_sink_type>(\r
+                       boost::log::keywords::file_name = (folder + L"caspar_%Y-%m-%d.log"),\r
+                       boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),\r
+                       boost::log::keywords::auto_flush = true,\r
+                       boost::log::keywords::open_mode = std::ios::app\r
+               );\r
+\r
+               bool print_all_characters = true;\r
+\r
+               file_sink->locked_backend()->set_formatter(boost::bind(my_formatter, print_all_characters, _1, _2));\r
+\r
+//#ifdef NDEBUG\r
+//             file_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
+//#else\r
+//             file_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
+//#endif\r
+               boost::log::wcore::get()->add_sink(file_sink);\r
+       }\r
+       catch(...)\r
+       {\r
+               std::wcerr << L"Failed to Setup File Logging Sink" << std::endl << std::endl;\r
+       }\r
+}\r
+\r
+void set_log_level(const std::wstring& lvl)\r
+{      \r
+       if(boost::iequals(lvl, L"trace"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= trace);\r
+       else if(boost::iequals(lvl, L"debug"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
+       else if(boost::iequals(lvl, L"info"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= info);\r
+       else if(boost::iequals(lvl, L"warning"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= warning);\r
+       else if(boost::iequals(lvl, L"error"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= error);\r
+       else if(boost::iequals(lvl, L"fatal"))\r
+               boost::log::wcore::get()->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= fatal);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/common/log/log.h b/common/log/log.h
new file mode 100644 (file)
index 0000000..39b615d
--- /dev/null
@@ -0,0 +1,125 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4100)\r
+#pragma warning (disable : 4127) // conditional expression is constant\r
+#pragma warning (disable : 4512)\r
+#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#pragma warning (disable : 4996) // _CRT_SECURE_NO_WARNINGS\r
+#endif\r
+\r
+#include <boost/log/detail/prologue.hpp>\r
+#include <boost/log/keywords/severity.hpp>\r
+#include <boost/log/sources/global_logger_storage.hpp>\r
+#include <boost/log/sources/severity_logger.hpp>\r
+#include <boost/log/sources/record_ostream.hpp>\r
+\r
+#include <string>\r
+#include <locale>\r
+\r
+namespace caspar { namespace log {\r
+       \r
+namespace internal{\r
+void init();\r
+}\r
+\r
+void add_file_sink(const std::wstring& folder);\r
+\r
+enum severity_level\r
+{\r
+       trace,\r
+       debug,\r
+       info,\r
+       warning,\r
+       error,\r
+       fatal\r
+};\r
+\r
+template< typename CharT, typename TraitsT >\r
+inline std::basic_ostream< CharT, TraitsT >& operator<< (\r
+       std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)\r
+{\r
+       if(lvl == trace)\r
+               strm << "trace";\r
+       else if(lvl == debug)\r
+               strm << "debug";\r
+       else if(lvl == info)\r
+               strm << "info";\r
+       else if(lvl == warning)\r
+               strm << "warning";\r
+       else if(lvl == error)\r
+               strm << "error";\r
+       else if(lvl == fatal)\r
+               strm << "fatal";\r
+       else\r
+               strm << static_cast<int>(lvl);\r
+\r
+       return strm;\r
+}\r
+\r
+typedef boost::log::sources::wseverity_logger_mt<severity_level> caspar_logger;\r
+\r
+BOOST_LOG_DECLARE_GLOBAL_LOGGER_INIT(logger, caspar_logger)\r
+{\r
+       internal::init();\r
+       return caspar_logger(boost::log::keywords::severity = trace);\r
+}\r
+\r
+#define CASPAR_LOG(lvl)\\r
+       BOOST_LOG_STREAM_WITH_PARAMS(::caspar::log::get_logger(),\\r
+               (::boost::log::keywords::severity = ::caspar::log::lvl))\r
+\r
+#define CASPAR_LOG_CURRENT_EXCEPTION() \\r
+       try\\r
+       {CASPAR_LOG(error) << boost::current_exception_diagnostic_information().c_str();}\\r
+       catch(...){}\r
+\r
+void set_log_level(const std::wstring& lvl);\r
+\r
+template<typename T>\r
+inline void replace_nonprintable(std::basic_string<T, std::char_traits<T>, std::allocator<T>>& str, T with)\r
+{\r
+       std::locale loc;\r
+       std::replace_if(str.begin(), str.end(), [&](T c)->bool {\r
+               return \r
+                       (!std::isprint(c, loc) \r
+                       && c != '\r' \r
+                       && c != '\n')\r
+                       || c > static_cast<T>(127);\r
+       }, with);\r
+}\r
+\r
+template<typename T>\r
+inline std::basic_string<T> replace_nonprintable_copy(std::basic_string<T, std::char_traits<T>, std::allocator<T>> str, T with)\r
+{\r
+       replace_nonprintable(str, with);\r
+       return str;\r
+}\r
+\r
+}}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif
\ No newline at end of file
diff --git a/common/memory/memclr.h b/common/memory/memclr.h
new file mode 100644 (file)
index 0000000..f80e167
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <assert.h>\r
+\r
+#include <cstring>\r
+\r
+namespace caspar {\r
+\r
+static void* fast_memclr(void* dest, size_t count)\r
+{\r
+       if(count < 2048)\r
+               return memset(dest, 0, count);\r
+\r
+       assert(dest != nullptr);\r
+       \r
+       size_t rest = count % 128;\r
+       count -= rest;\r
+\r
+       __asm   \r
+       {              \r
+               mov edi, dest;    \r
+               mov ebx, count;     \r
+               shr ebx, 7;\r
+               pxor xmm0, xmm0; \r
+\r
+               clr:             \r
+                       movntdq [edi+00h], xmm0;\r
+                       movntdq [edi+10h], xmm0;\r
+                       movntdq [edi+20h], xmm0;    \r
+                       movntdq [edi+30h], xmm0;\r
+                       \r
+                       movntdq [edi+40h], xmm0; \r
+                       movntdq [edi+50h], xmm0;      \r
+                       movntdq [edi+60h], xmm0;    \r
+                       movntdq [edi+70h], xmm0;    \r
+\r
+                       lea edi, [edi+80h];         \r
+\r
+                       dec ebx;      \r
+               jnz clr;  \r
+       }   \r
+       return memset(reinterpret_cast<char*>(dest)+count, 0, rest);\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/memory/memcpy.h b/common/memory/memcpy.h
new file mode 100644 (file)
index 0000000..4885138
--- /dev/null
@@ -0,0 +1,192 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../utility/assert.h"\r
+#include "../memory/safe_ptr.h"\r
+\r
+#include <assert.h>\r
+\r
+#include <tbb/parallel_for.h>\r
+\r
+namespace caspar {\r
+\r
+namespace detail {\r
+\r
+static void* fast_memcpy_aligned_impl(void* dest, const void* source, size_t count)\r
+{\r
+       CASPAR_ASSERT(dest != nullptr);\r
+       CASPAR_ASSERT(source != nullptr);\r
+       CASPAR_ASSERT(reinterpret_cast<int>(dest) % 16 == 0);\r
+       CASPAR_ASSERT(reinterpret_cast<int>(source) % 16 == 0);\r
+\r
+       if(count == 0)\r
+               return dest;\r
+\r
+       __asm   \r
+       {      \r
+               mov esi, source;          \r
+               mov edi, dest;    \r
+               mov ebx, count;     \r
+               shr ebx, 7;\r
+\r
+               cpy:             \r
+                       movdqa xmm0, [esi+00h];       \r
+                       movdqa xmm1, [esi+10h];      \r
+                       movdqa xmm2, [esi+20h];         \r
+                       movdqa xmm3, [esi+30h];   \r
+\r
+                       movntdq [edi+00h], xmm0;\r
+                       movntdq [edi+10h], xmm1;\r
+                       movntdq [edi+20h], xmm2;    \r
+                       movntdq [edi+30h], xmm3;\r
+\r
+                       movdqa xmm4, [esi+40h];\r
+                       movdqa xmm5, [esi+50h];\r
+                       movdqa xmm6, [esi+60h];\r
+                       movdqa xmm7, [esi+70h];  \r
+\r
+                       movntdq [edi+40h], xmm4; \r
+                       movntdq [edi+50h], xmm5;      \r
+                       movntdq [edi+60h], xmm6;    \r
+                       movntdq [edi+70h], xmm7;    \r
+\r
+                       lea edi, [edi+80h];       \r
+                       lea esi, [esi+80h];      \r
+\r
+                       dec ebx;      \r
+               jnz cpy;  \r
+       }   \r
+       return dest;\r
+}\r
+\r
+static void* fast_memcpy_unaligned_impl(void* dest, const void* source, size_t count)\r
+{\r
+       CASPAR_ASSERT(dest != nullptr);\r
+       CASPAR_ASSERT(source != nullptr);\r
+\r
+       if(count == 0)\r
+               return dest;\r
+\r
+       __asm   \r
+       {      \r
+               mov esi, source;          \r
+               mov edi, dest;    \r
+               mov ebx, count;     \r
+               shr ebx, 7;\r
+\r
+               cpy:             \r
+                       movdqu xmm0, [esi+00h];       \r
+                       movdqu xmm1, [esi+10h];      \r
+                       movdqu xmm2, [esi+20h];         \r
+                       movdqu xmm3, [esi+30h];   \r
+\r
+                       movdqu [edi+00h], xmm0;\r
+                       movdqu [edi+10h], xmm1;\r
+                       movdqu [edi+20h], xmm2;    \r
+                       movdqu [edi+30h], xmm3;\r
+\r
+                       movdqu xmm4, [esi+40h];\r
+                       movdqu xmm5, [esi+50h];\r
+                       movdqu xmm6, [esi+60h];\r
+                       movdqu xmm7, [esi+70h];  \r
+\r
+                       movdqu [edi+40h], xmm4; \r
+                       movdqu [edi+50h], xmm5;      \r
+                       movdqu [edi+60h], xmm6;    \r
+                       movdqu [edi+70h], xmm7;    \r
+\r
+                       lea edi, [edi+80h];       \r
+                       lea esi, [esi+80h];      \r
+\r
+                       dec ebx;      \r
+               jnz cpy;  \r
+       }   \r
+       return dest;\r
+}\r
+\r
+static void* fast_memcpy_small_aligned(char* dest8, const char* source8, size_t count)\r
+{   \r
+       size_t rest = count & 127;\r
+       count &= ~127;\r
+\r
+       fast_memcpy_aligned_impl(dest8, source8, count);   \r
+\r
+       return memcpy(dest8+count,  source8+count, rest);\r
+}\r
+\r
+static void* fast_memcpy_small_unaligned(char* dest8, const char* source8, size_t count)\r
+{   \r
+       size_t rest = count & 127;\r
+       count &= ~127;\r
+\r
+       fast_memcpy_unaligned_impl(dest8, source8, count);   \r
+\r
+       return memcpy(dest8+count,  source8+count, rest);\r
+}\r
+\r
+static void* fast_memcpy_aligned(void* dest, const void* source, size_t count)\r
+{   \r
+       auto dest8                      = reinterpret_cast<char*>(dest);\r
+       auto source8            = reinterpret_cast<const char*>(source);\r
+               \r
+       size_t rest = count & 2047;\r
+       count &= ~2047;\r
+               \r
+       tbb::affinity_partitioner ap;\r
+       tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
+       {       \r
+               fast_memcpy_aligned_impl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128);   \r
+       }, ap);\r
+       \r
+       return fast_memcpy_small_aligned(dest8+count, source8+count, rest);\r
+}\r
+\r
+static void* fast_memcpy_unaligned(void* dest, const void* source, size_t count)\r
+{   \r
+       auto dest8                      = reinterpret_cast<char*>(dest);\r
+       auto source8            = reinterpret_cast<const char*>(source);\r
+               \r
+       size_t rest = count & 2047;\r
+       count &= ~2047;\r
+               \r
+       tbb::affinity_partitioner ap;\r
+       tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
+       {       \r
+               fast_memcpy_unaligned_impl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128);   \r
+       }, ap);\r
+       \r
+       return fast_memcpy_small_unaligned(dest8+count, source8+count, rest);\r
+}\r
+\r
+}\r
+\r
+template<typename T>\r
+T* fast_memcpy(T* dest, const void* source, size_t count)\r
+{   \r
+       if((reinterpret_cast<int>(source) & 15) || (reinterpret_cast<int>(dest) & 15))\r
+               return reinterpret_cast<T*>(detail::fast_memcpy_unaligned(dest, source, count));\r
+       else\r
+               return reinterpret_cast<T*>(detail::fast_memcpy_aligned(dest, source, count));\r
+}\r
+\r
+}\r
diff --git a/common/memory/memshfl.h b/common/memory/memshfl.h
new file mode 100644 (file)
index 0000000..c776e3b
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <intrin.h>\r
+\r
+#include <assert.h>\r
+\r
+#include <tbb/parallel_for.h>\r
+\r
+namespace caspar {\r
+\r
+namespace internal {\r
+\r
+static void* fast_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
+{\r
+       __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
+       const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\r
+\r
+       count /= 16; // 128 bit\r
+\r
+       __m128i xmm0, xmm1, xmm2, xmm3;\r
+\r
+       const __m128i mask128 = _mm_set_epi32(m1, m2, m3, m4);\r
+       for(size_t n = 0; n < count/4; ++n)\r
+       {\r
+               xmm0 = _mm_load_si128(source128++);     \r
+               xmm1 = _mm_load_si128(source128++);     \r
+               xmm2 = _mm_load_si128(source128++);     \r
+               xmm3 = _mm_load_si128(source128++);     \r
+\r
+               _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm0, mask128));\r
+               _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm1, mask128));\r
+               _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm2, mask128));\r
+               _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm3, mask128));\r
+       }\r
+       return dest;\r
+}\r
+\r
+}\r
+\r
+static void* fast_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
+{   \r
+       tbb::affinity_partitioner ap;\r
+       tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
+       {       \r
+               internal::fast_memshfl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128, m1, m2, m3, m4);   \r
+       }, ap);\r
+\r
+       return dest;\r
+}\r
+\r
+\r
+}
\ No newline at end of file
diff --git a/common/memory/page_locked_allocator.h b/common/memory/page_locked_allocator.h
new file mode 100644 (file)
index 0000000..38863e4
--- /dev/null
@@ -0,0 +1,132 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <unordered_map>\r
+#include <tbb/mutex.h>\r
+\r
+namespace caspar\r
+{\r
+       \r
+template <class T>\r
+class page_locked_allocator\r
+{\r
+public:\r
+       typedef size_t    size_type;\r
+       typedef ptrdiff_t difference_type;\r
+       typedef T*        pointer;\r
+       typedef const T*  const_pointer;\r
+       typedef T&        reference;\r
+       typedef const T&  const_reference;\r
+       typedef T         value_type;\r
+\r
+       page_locked_allocator() {}\r
+       page_locked_allocator(const page_locked_allocator&) {}\r
+  \r
+       pointer allocate(size_type n, const void * = 0) \r
+       {\r
+               tbb::mutex::scoped_lock lock(get().mutex);\r
+\r
+               size_type size = n * sizeof(T);         \r
+               if(get().free < size)\r
+                       allocate_store(size);\r
+\r
+               auto p = ::VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r
+               if(!p)\r
+                       throw std::bad_alloc();\r
+\r
+               if(::VirtualLock(p, size) == 0) \r
+               {\r
+                       ::VirtualFree(p, 0, MEM_RELEASE);\r
+                       throw std::bad_alloc();\r
+               }\r
+               \r
+               get().free -= size;\r
+               get().map[p] = size;\r
+               return reinterpret_cast<T*>(p);\r
+       }\r
+  \r
+       void deallocate(void* p, size_type) \r
+       {\r
+               tbb::mutex::scoped_lock lock(get().mutex);\r
+\r
+               if(!p || get().map.find(p) == get().map.end())\r
+                       return;\r
+\r
+               try\r
+               {\r
+                       ::VirtualFree(p, 0, MEM_RELEASE);\r
+                       get().free += get().map[p];\r
+                       get().map.erase(p);\r
+               }\r
+               catch(...){}            \r
+       }\r
+\r
+       pointer           address(reference x) const { return &x; }\r
+       const_pointer     address(const_reference x) const { return &x; }\r
+       page_locked_allocator<T>&  operator=(const page_locked_allocator&) { return *this; }\r
+       void              construct(pointer p, const T& val) { new ((T*) p) T(val); }\r
+       void              destroy(pointer p) { p->~T(); }\r
+\r
+       size_type         max_size() const { return size_t(-1); }\r
+\r
+       template <class U>\r
+       struct rebind { typedef page_locked_allocator<U> other; };\r
+\r
+       template <class U>\r
+       page_locked_allocator(const page_locked_allocator<U>&) {}\r
+\r
+       template <class U>\r
+       page_locked_allocator& operator=(const page_locked_allocator<U>&) { return *this; }\r
+\r
+private:\r
+\r
+       void allocate_store(size_type size)\r
+       {               \r
+               SIZE_T workingSetMinSize = 0, workingSetMaxSize = 0;\r
+               if(::GetProcessWorkingSetSize(::GetCurrentProcess(), &workingSetMinSize, &workingSetMaxSize))\r
+               {                       \r
+                       workingSetMinSize += size;\r
+                       workingSetMaxSize += size;\r
+\r
+                       if(!::SetProcessWorkingSetSize(::GetCurrentProcess(), workingSetMinSize, workingSetMaxSize))            \r
+                               throw std::bad_alloc();         \r
+\r
+                       get().free += size;\r
+               }\r
+       }\r
+\r
+       struct impl\r
+       {\r
+               impl() : free(0){}\r
+               std::unordered_map<void*, size_type> map;\r
+               size_type free;\r
+               tbb::mutex mutex;\r
+       };\r
+\r
+       static impl& get()\r
+       {\r
+               static impl i;\r
+               return i;\r
+       }\r
+};\r
+}
\ No newline at end of file
diff --git a/common/memory/safe_ptr.h b/common/memory/safe_ptr.h
new file mode 100644 (file)
index 0000000..227af65
--- /dev/null
@@ -0,0 +1,430 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <memory>\r
+#include <stdexcept>\r
+#include <type_traits>\r
+\r
+namespace caspar\r
+{\r
+\r
+template<typename T>\r
+class safe_ptr\r
+{   \r
+    template <typename> friend class safe_ptr;\r
+public:\r
+    typedef T  element_type;\r
+\r
+    safe_ptr(); // will construct new T object using make_safe<T>()\r
+\r
+    safe_ptr(const safe_ptr& other) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    template<typename U>\r
+    safe_ptr(const safe_ptr<U>& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    safe_ptr(safe_ptr&& other) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    template<typename U>\r
+    safe_ptr(safe_ptr<U>&& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+       \r
+    template<typename U>    \r
+    explicit safe_ptr(const std::shared_ptr<U>& p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U>    \r
+    explicit safe_ptr(std::shared_ptr<U>&& p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(std::move(p))\r
+    {\r
+        if(!p_)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U>    \r
+    explicit safe_ptr(U* p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U, typename D>    \r
+    explicit safe_ptr(U* p, D d, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p, d)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+    \r
+    template<typename U>\r
+    typename std::enable_if<std::is_convertible<U*, T*>::value, safe_ptr&>::type\r
+    operator=(const safe_ptr<U>& other)\r
+    {\r
+        safe_ptr(other).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+    template<typename U>\r
+    typename std::enable_if<std::is_convertible<U*, T*>::value, safe_ptr&>::type\r
+    operator=(safe_ptr<U>&& other)\r
+    {\r
+        safe_ptr<T>(std::move(other)).swap(*this);\r
+        return *this;\r
+    }\r
+       \r
+    T& operator*() const \r
+    { \r
+        return *p_.get();\r
+    }\r
+\r
+    T* operator->() const \r
+    { \r
+        return p_.get();\r
+    }\r
+\r
+    T* get() const \r
+    { \r
+        return p_.get();\r
+    }\r
+\r
+    bool unique() const \r
+    { \r
+        return p_.unique();\r
+    }\r
+\r
+    long use_count() const \r
+    {\r
+        return p_.use_count();\r
+    }\r
+\r
+    void swap(safe_ptr& other) \r
+    { \r
+        p_.swap(other.p_); \r
+    } \r
+\r
+    operator std::shared_ptr<T>() const \r
+    { \r
+        return p_;\r
+    }\r
+\r
+    operator std::weak_ptr<T>() const \r
+    { \r
+        return std::weak_ptr<T>(p_);\r
+    }\r
+    \r
+    template<class U>\r
+    bool owner_before(const safe_ptr& ptr)\r
+    { \r
+        return p_.owner_before(ptr.p_); \r
+    }\r
+\r
+    template<class U>\r
+    bool owner_before(const std::shared_ptr<U>& ptr)\r
+    { \r
+        return p_.owner_before(ptr); \r
+    }\r
+\r
+    template<class D, class U> \r
+    D* get_deleter(safe_ptr<U> const& ptr) \r
+    { \r
+        return p_.get_deleter(); \r
+    }\r
+\r
+private:    \r
+    std::shared_ptr<T> p_;\r
+};\r
+\r
+template<class T, class U>\r
+bool operator==(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator==(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator==(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() < b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() < b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() < b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() > b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() > b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() > b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() >= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() >= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator>=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() >= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
+}\r
+\r
+template<class E, class T, class U>\r
+std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& out, const safe_ptr<U>& p)\r
+{\r
+    return out << p.get();\r
+}\r
+\r
+template<class T> \r
+void swap(safe_ptr<T>& a, safe_ptr<T>& b)\r
+{\r
+    a.swap(b);\r
+}\r
+\r
+template<class T> \r
+T* get_pointer(safe_ptr<T> const& p)\r
+{\r
+    return p.get();\r
+}\r
+\r
+template <class T, class U>\r
+safe_ptr<T> static_pointer_cast(const safe_ptr<U>& p)\r
+{\r
+    return safe_ptr<T>(std::static_pointer_cast<T>(std::shared_ptr<U>(p)));\r
+}\r
+\r
+template <class T, class U>\r
+safe_ptr<T> const_pointer_cast(const safe_ptr<U>& p)\r
+{\r
+    return safe_ptr<T>(std::const_pointer_cast<T>(std::shared_ptr<U>(p)));\r
+}\r
+\r
+template <class T, class U>\r
+safe_ptr<T> dynamic_pointer_cast(const safe_ptr<U>& p)\r
+{\r
+    auto temp = std::dynamic_pointer_cast<T>(std::shared_ptr<U>(p));\r
+    if(!temp)\r
+        throw std::bad_cast();\r
+    return safe_ptr<T>(std::move(temp));\r
+}\r
+\r
+//\r
+// enable_safe_this \r
+//\r
+// A safe_ptr version of enable_shared_from_this.\r
+// So that an object may get safe_ptr objects to itself.\r
+//\r
+\r
+template<class T>\r
+class enable_safe_from_this : public std::enable_shared_from_this<T>\r
+{\r
+public:\r
+    safe_ptr<T> safe_from_this() \r
+    {\r
+        return safe_ptr<T>(this->shared_from_this());\r
+    }\r
+\r
+    safe_ptr<T const> safe_from_this() const \r
+    {\r
+        return safe_ptr<T const>(this->shared_from_this());\r
+    }\r
+protected:\r
+    enable_safe_from_this()\r
+    {\r
+    }\r
+    \r
+    enable_safe_from_this(const enable_safe_from_this&)\r
+    {\r
+    }\r
+    \r
+    enable_safe_from_this& operator=(const enable_safe_from_this&)\r
+    {        \r
+        return *this;\r
+    }\r
+    \r
+    ~enable_safe_from_this ()\r
+    {\r
+    }\r
+};\r
+\r
+//\r
+// make_safe\r
+//\r
+// safe_ptr equivalents to make_shared\r
+//\r
+\r
+template<typename T>\r
+safe_ptr<T> make_safe_ptr(const std::shared_ptr<T>& ptr)\r
+{\r
+       return safe_ptr<T>(ptr);\r
+}\r
+\r
+template<typename T>\r
+safe_ptr<T> make_safe_ptr(std::shared_ptr<T>&& ptr)\r
+{\r
+       return safe_ptr<T>(ptr);\r
+}\r
+\r
+template<typename T>\r
+safe_ptr<T> make_safe()\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>());\r
+}\r
+\r
+template<typename T, typename P0>\r
+safe_ptr<T> make_safe(P0&& p0)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2, typename P3>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)\r
+{\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6)\r
+{\r
+       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6)));\r
+}\r
+\r
+template<typename T>\r
+safe_ptr<T>::safe_ptr() \r
+    : p_(make_safe<T>())\r
+{\r
+} \r
+\r
+} // namespace\r
diff --git a/common/os/windows/current_version.h b/common/os/windows/current_version.h
new file mode 100644 (file)
index 0000000..174bffa
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <windows.h>\r
+\r
+#include <string>\r
+\r
+namespace caspar {\r
+\r
+static std::wstring get_win_product_name()\r
+{\r
+       std::wstring result = L"Unknown Windows Product Name.";\r
+       HKEY hkey; \r
+       DWORD dwType, dwSize;\r
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
+       {\r
+               wchar_t p_name_str[1024];\r
+\r
+               dwType = REG_SZ;\r
+               dwSize = sizeof(p_name_str);\r
+\r
+               if(RegQueryValueEx(hkey, TEXT("ProductName"), NULL, &dwType, (PBYTE)&p_name_str, &dwSize) == ERROR_SUCCESS)             \r
+                       result = p_name_str;            \r
+                \r
+               RegCloseKey(hkey);\r
+       }\r
+       return result;\r
+}\r
+\r
+static std::wstring get_win_sp_version()\r
+{\r
+       std::wstring result =  L"";\r
+       HKEY hkey; \r
+       DWORD dwType, dwSize;\r
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
+       {\r
+               wchar_t csd_ver_str[1024];\r
+\r
+               dwType = REG_SZ;\r
+               dwSize = sizeof(csd_ver_str);\r
+\r
+               if(RegQueryValueEx(hkey, TEXT("CSDVersion"), NULL, &dwType, (PBYTE)&csd_ver_str, &dwSize) == ERROR_SUCCESS)             \r
+                       result = csd_ver_str;\r
+                \r
+               RegCloseKey(hkey);\r
+       }\r
+       return result;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/os/windows/system_info.h b/common/os/windows/system_info.h
new file mode 100644 (file)
index 0000000..a6d58eb
--- /dev/null
@@ -0,0 +1,85 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <windows.h>\r
+\r
+#include <string>\r
+#include <sstream>\r
+\r
+namespace caspar {\r
+       \r
+static std::wstring get_cpu_info()\r
+{\r
+       std::wstring cpu_name = L"Unknown CPU";\r
+       HKEY hkey; \r
+       DWORD dwType, dwSize;\r
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
+       {\r
+               wchar_t p_name_str[1024];\r
+\r
+               dwType = REG_SZ;\r
+               dwSize = sizeof(p_name_str);\r
+\r
+               if(RegQueryValueEx(hkey, TEXT("ProcessorNameString"), NULL, &dwType, (PBYTE)&p_name_str, &dwSize) == ERROR_SUCCESS)             \r
+                       cpu_name = p_name_str;          \r
+                \r
+               RegCloseKey(hkey);\r
+       }\r
+\r
+\r
+       SYSTEM_INFO sysinfo;\r
+       GetSystemInfo(&sysinfo);\r
+\r
+       std::wstringstream s;\r
+\r
+       s << cpu_name << L" Physical Threads: " << sysinfo.dwNumberOfProcessors;\r
+\r
+       return s.str();\r
+}\r
+\r
+static std::wstring get_system_product_name()\r
+{\r
+       std::wstring system_product_name = L"Unknown System";\r
+       HKEY hkey; \r
+       DWORD dwType, dwSize;\r
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\BIOS"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
+       {\r
+               wchar_t p_name_str[1024];\r
+\r
+               dwType = REG_SZ;\r
+               dwSize = sizeof(p_name_str);\r
+\r
+               if(RegQueryValueEx(hkey, TEXT("SystemProductName"), NULL, &dwType, (PBYTE)&p_name_str, &dwSize) == ERROR_SUCCESS)               \r
+                       system_product_name = p_name_str;               \r
+                \r
+               RegCloseKey(hkey);\r
+       }\r
+\r
+       return system_product_name;\r
+}\r
+\r
+\r
+}
\ No newline at end of file
diff --git a/common/printable.h b/common/printable.h
new file mode 100644 (file)
index 0000000..9e90864
--- /dev/null
@@ -0,0 +1,44 @@
+#pragma once\r
+\r
+#include <string>\r
+\r
+#include <tbb/spin_mutex.h>\r
+\r
+namespace caspar {\r
+\r
+class printable\r
+{\r
+       mutable tbb::spin_mutex mutex_;\r
+       const printable* parent_;\r
+public:\r
+       printable(const printable* parent = nullptr){set_parent(parent);}\r
+\r
+       std::wstring print() const\r
+       {\r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               return (parent_ ? parent_->print() + L"/" : L"") + do_print();\r
+       }\r
+       \r
+       virtual void swap(object& other)\r
+       {\r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               std::swap(parent_, other.parent_);\r
+       }\r
+       \r
+       const object* get_parent() const\r
+       {\r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               return parent_;\r
+       }\r
+\r
+       void set_parent(const object* parent)\r
+       {\r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               parent_ = parent != this ? parent : nullptr;\r
+       }\r
+\r
+private:\r
+       virtual std::wstring do_print() const = 0;\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/common/stdafx.cpp b/common/stdafx.cpp
new file mode 100644 (file)
index 0000000..923b06b
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"\r
diff --git a/common/stdafx.h b/common/stdafx.h
new file mode 100644 (file)
index 0000000..3d4ef7d
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <windows.h>\r
+#include <GL/glew.h>\r
+\r
+#include "compiler\vs\disable_silly_warnings.h"\r
+\r
+#include <string>\r
+#include <cassert>\r
diff --git a/common/utility/assert.h b/common/utility/assert.h
new file mode 100644 (file)
index 0000000..18be7cb
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../log/log.h"\r
+\r
+#ifdef _MSC_VER\r
+#define _CASPAR_DBG_BREAK _CrtDbgBreak()\r
+#else\r
+#define _CASPAR_DBG_BREAK\r
+#endif\r
+\r
+#define CASPAR_VERIFY_EXPR_STR(str) #str\r
+\r
+#define CASPAR_VERIFY(expr) do{if(!(expr)){ CASPAR_LOG(warning) << "Assertion Failed: " << \\r
+       CASPAR_VERIFY_EXPR_STR(expr) << " " \\r
+       << "file:" << __FILE__ << " " \\r
+       << "line:" << __LINE__ << " "; \\r
+       _CASPAR_DBG_BREAK;\\r
+       }}while(0);\r
+\r
+#ifdef _DEBUG\r
+#define CASPAR_ASSERT(expr) CASPAR_VERIFY(expr)\r
+#else\r
+#define CASPAR_ASSERT(expr)\r
+#endif
\ No newline at end of file
diff --git a/common/utility/move_on_copy.h b/common/utility/move_on_copy.h
new file mode 100644 (file)
index 0000000..0c272e5
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar {\r
+               \r
+template<typename T>\r
+struct move_on_copy\r
+{\r
+       move_on_copy(const move_on_copy<T>& other) : value(std::move(other.value)){}\r
+       move_on_copy(T&& value) : value(std::move(value)){}\r
+       mutable T value;\r
+};\r
+\r
+template<typename T>\r
+move_on_copy<T> make_move_on_copy(T&& value)\r
+{\r
+       return move_on_copy<T>(std::move(value));\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/param.h b/common/utility/param.h
new file mode 100644 (file)
index 0000000..94ec492
--- /dev/null
@@ -0,0 +1,36 @@
+#pragma once\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#include <type_traits>\r
+#include <string>\r
+\r
+namespace caspar {\r
+               \r
+template<typename T, typename C>\r
+typename std::enable_if<!std::is_convertible<T, std::wstring>::value, typename std::decay<T>::type>::type get_param(const std::wstring& name, C&& params, T fail_value = T())\r
+{      \r
+       auto it = std::find(std::begin(params), std::end(params), name);\r
+       if(it == params.end() || ++it == params.end())  \r
+               return fail_value;\r
+       \r
+       T value = fail_value;\r
+       try\r
+       {\r
+               value = boost::lexical_cast<std::decay<T>::type>(*it);\r
+       }\r
+       catch(boost::bad_lexical_cast&){}\r
+\r
+       return value;\r
+}\r
+\r
+template<typename C>\r
+std::wstring get_param(const std::wstring& name, C&& params, const std::wstring& fail_value = L"")\r
+{      \r
+       auto it = std::find(std::begin(params), std::end(params), name);\r
+       if(it == params.end() || ++it == params.end())  \r
+               return fail_value;\r
+       return *it;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/string.cpp b/common/utility/string.cpp
new file mode 100644 (file)
index 0000000..33ba985
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include <boost/locale.hpp>\r
+\r
+#include "utf8conv.h"\r
+\r
+namespace caspar {\r
+       \r
+std::wstring widen(const std::string& str)\r
+{\r
+       return utf8util::UTF16FromUTF8(str);//std::wstring(str.begin(), str.end());\r
+}\r
+\r
+std::wstring widen(const std::wstring& str)\r
+{\r
+       return str;\r
+}\r
+          \r
+std::string narrow(const std::wstring& str)\r
+{\r
+       return utf8util::UTF8FromUTF16(str);//std::string(str.begin(), str.end());\r
+}\r
+          \r
+std::string narrow(const std::string& str)\r
+{\r
+       return str ;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/string.h b/common/utility/string.h
new file mode 100644 (file)
index 0000000..a7aee7a
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+#include <boost/lexical_cast.hpp>\r
+          \r
+namespace caspar {\r
+\r
+std::wstring widen(const std::string& str);\r
+std::wstring widen(const std::wstring& str);\r
+std::string narrow(const std::wstring& str);      \r
+std::string narrow(const std::string& str);\r
+\r
+template <typename T>\r
+inline T lexical_cast_or_default(const std::wstring str, T fail_value = T())\r
+{\r
+       try\r
+       {\r
+               return boost::lexical_cast<T>(str);\r
+       }\r
+       catch(boost::bad_lexical_cast&)\r
+       {\r
+               return fail_value;\r
+       }\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/timer.h b/common/utility/timer.h
new file mode 100644 (file)
index 0000000..79a3162
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#define NOMINMAX\r
+\r
+#include <windows.h>\r
+#include <Mmsystem.h>\r
+\r
+namespace caspar {\r
+       \r
+class high_prec_timer\r
+{\r
+public:\r
+       high_prec_timer()\r
+               : time_(0)\r
+       {\r
+       }\r
+\r
+       // Author: Ryan M. Geiss\r
+       // http://www.geisswerks.com/ryan/FAQS/timing.html\r
+       void tick(double interval)\r
+       {       \r
+               auto t = ::timeGetTime();\r
+\r
+               if (time_ != 0)\r
+               {\r
+                       auto ticks_to_wait = static_cast<DWORD>(interval*1000.0);\r
+                       bool done = 0;\r
+                       do\r
+                       {                               \r
+                               auto ticks_passed = t - time_;\r
+                               auto ticks_left   = ticks_to_wait - ticks_passed;\r
+\r
+                               if (t < time_)    // time wrap\r
+                                       done = 1;\r
+                               if (ticks_passed >= ticks_to_wait)\r
+                                       done = 1;\r
+                               \r
+                               if (!done)\r
+                               {\r
+                                       // if > 0.002s left, do Sleep(1), which will actually sleep some \r
+                                       //   steady amount, probably 1-2 ms,\r
+                                       //   and do so in a nice way (cpu meter drops; laptop battery spared).\r
+                                       // otherwise, do a few Sleep(0)'s, which just give up the timeslice,\r
+                                       //   but don't really save cpu or battery, but do pass a tiny\r
+                                       //   amount of time.\r
+                                       if (ticks_left > 2)\r
+                                               Sleep(1);\r
+                                       else                        \r
+                                               for (int i = 0; i < 10; ++i) \r
+                                                       Sleep(0);  // causes thread to give up its timeslice\r
+                               }\r
+\r
+                               t = ::timeGetTime();\r
+                       }\r
+                       while (!done);            \r
+               }\r
+\r
+               time_ = t;\r
+       }               \r
+private:       \r
+       DWORD time_;\r
+};\r
+\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/tweener.cpp b/common/utility/tweener.cpp
new file mode 100644 (file)
index 0000000..0cff3c1
--- /dev/null
@@ -0,0 +1,456 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+\r
+// The following code is based on Tweener for actionscript, http://code.google.com/p/tweener/\r
+//\r
+//Disclaimer for Robert Penner's Easing Equations license:\r
+//\r
+//TERMS OF USE - EASING EQUATIONS\r
+//\r
+//Open source under the BSD License.\r
+//\r
+//Copyright © 2001 Robert Penner\r
+//All rights reserved.\r
+//\r
+//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\r
+//\r
+//    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\r
+//    * 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.\r
+//    * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.\r
+//\r
+//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.\r
+#include "../stdafx.h"\r
+\r
+#include "tweener.h"\r
+\r
+#include <boost/assign/list_of.hpp>\r
+#include <boost/regex.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#include <unordered_map>\r
+#include <string>\r
+#include <locale>\r
+#include <functional>\r
+#include <vector>\r
+\r
+namespace caspar {\r
+\r
+typedef std::function<double(double, double, double, double)> tweener_t;\r
+                       \r
+static const double PI = std::atan(1.0)*4.0;\r
+static const double H_PI = std::atan(1.0)*2.0;\r
+\r
+double ease_none (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*t/d + b;\r
+}\r
+\r
+double ease_in_quad (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*(t/=d)*t + b;\r
+}\r
+       \r
+double ease_out_quad (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return -c *(t/=d)*(t-2) + b;\r
+}      \r
+\r
+double ease_in_out_quad (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       if ((t/=d/2) < 1) \r
+               return c/2*t*t + b;\r
+\r
+       return -c/2 * ((--t)*(t-2) - 1) + b;\r
+}      \r
+\r
+double ease_out_in_quad (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       if (t < d/2) \r
+               return ease_out_quad (t*2, b, c/2, d, params);\r
+\r
+       return ease_in_quad((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_in_cubic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*(t/=d)*t*t + b;\r
+}      \r
+\r
+double ease_out_cubic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*((t=t/d-1)*t*t + 1) + b;\r
+}\r
+       \r
+double ease_in_out_cubic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if ((t/=d/2) < 1) \r
+               return c/2*t*t*t + b;\r
+\r
+       return c/2*((t-=2)*t*t + 2) + b;\r
+}\r
+       \r
+double ease_out_in_cubic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) return ease_out_cubic (t*2, b, c/2, d, params);\r
+       return ease_in_cubic((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_in_quart (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*(t/=d)*t*t*t + b;\r
+}\r
+       \r
+double ease_out_quart (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return -c * ((t=t/d-1)*t*t*t - 1) + b;\r
+}      \r
+\r
+double ease_in_out_quart (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if ((t/=d/2) < 1)\r
+               return c/2*t*t*t*t + b;\r
+\r
+       return -c/2 * ((t-=2)*t*t*t - 2) + b;\r
+}      \r
+\r
+double ease_out_in_quart (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2)\r
+               return ease_out_quart (t*2, b, c/2, d, params);\r
+\r
+       return ease_in_quart((t*2)-d, b+c/2, c/2, d, params);\r
+}      \r
+\r
+double ease_in_quint (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*(t/=d)*t*t*t*t + b;\r
+}\r
+       \r
+double ease_out_quint (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c*((t=t/d-1)*t*t*t*t + 1) + b;\r
+}\r
+       \r
+double ease_in_out_quint (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if ((t/=d/2) < 1) \r
+               return c/2*t*t*t*t*t + b;\r
+\r
+       return c/2*((t-=2)*t*t*t*t + 2) + b;\r
+}\r
+       \r
+double ease_out_in_quint (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) \r
+               return ease_out_quint (t*2, b, c/2, d, params);\r
+\r
+       return ease_in_quint((t*2)-d, b+c/2, c/2, d, params);\r
+}      \r
+\r
+double ease_in_sine (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return -c * std::cos(t/d * (PI/2)) + c + b;\r
+}      \r
+\r
+double ease_out_sine (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c * std::sin(t/d * (PI/2)) + b;\r
+}      \r
+\r
+double ease_in_out_sine (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return -c/2 * (std::cos(PI*t/d) - 1) + b;\r
+}      \r
+\r
+double ease_out_in_sine (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       if (t < d/2) \r
+               return ease_out_sine (t*2, b, c/2, d, params);\r
+       \r
+       return ease_in_sine((t*2)-d, b+c/2, c/2, d, params);\r
+}      \r
+\r
+double ease_in_expo (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return (t==0) ? b : c * std::pow(2, 10 * (t/d - 1)) + b - c * 0.001;\r
+}      \r
+\r
+double ease_out_expo (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return (t==d) ? b+c : c * 1.001 * (-std::pow(2, -10 * t/d) + 1) + b;\r
+}\r
+       \r
+double ease_in_out_expo (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t==0) \r
+               return b;\r
+       if (t==d) \r
+               return b+c;\r
+       if ((t/=d/2) < 1) \r
+               return c/2 * std::pow(2, 10 * (t - 1)) + b - c * 0.0005;\r
+\r
+       return c/2 * 1.0005 * (-std::pow(2, -10 * --t) + 2) + b;\r
+}\r
+       \r
+double ease_out_in_expo (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) \r
+               return ease_out_expo (t*2, b, c/2, d, params);\r
+\r
+       return ease_in_expo((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_in_circ (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return -c * (std::sqrt(1 - (t/=d)*t) - 1) + b;\r
+}\r
+       \r
+double ease_out_circ (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       return c * std::sqrt(1 - (t=t/d-1)*t) + b;\r
+}\r
+       \r
+double ease_in_out_circ (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if ((t/=d/2) < 1) \r
+               return -c/2 * (std::sqrt(1 - t*t) - 1) + b;\r
+\r
+       return c/2 * (std::sqrt(1 - (t-=2)*t) + 1) + b;\r
+}\r
+       \r
+double ease_out_in_circ (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) return ease_out_circ(t*2, b, c/2, d, params);\r
+       return ease_in_circ((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_in_elastic (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       if (t==0) return b;\r
+       if ((t/=d)==1) return b+c;\r
+       //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;\r
+       //var s:Number;\r
+       //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\r
+       double p = params.size() > 0 ? params[0] : d*0.3;\r
+       double s;\r
+       double a = params.size() > 1 ? params[1] : 0.0;\r
+       if (a == 0.0 || a < std::abs(c)) \r
+       {\r
+               a = c;\r
+               s = p/4;\r
+       } \r
+       else \r
+               s = p/(2*PI) * std::asin (c/a);\r
+       \r
+       return -(a*std::pow(2,10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )) + b;\r
+}\r
+       \r
+double ease_out_elastic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t==0) \r
+               return b;\r
+       if ((t/=d)==1) \r
+               return b+c;\r
+       //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;\r
+       //var s:Number;\r
+       //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\r
+       double p = params.size() > 0 ? params[0] : d*0.3;\r
+       double s;\r
+       double a = params.size() > 1 ? params[1] : 0.0;\r
+       if (a == 0.0 || a < std::abs(c))\r
+       {\r
+               a = c;\r
+               s = p/4;\r
+       } \r
+       else \r
+               s = p/(2*PI) * std::asin (c/a);\r
+       \r
+       return (a*std::pow(2,-10*t) * std::sin( (t*d-s)*(2*PI)/p ) + c + b);\r
+}      \r
+\r
+double ease_in_out_elastic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t==0)\r
+               return b;\r
+       if ((t/=d/2)==2) \r
+               return b+c;\r
+       //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*(.3*1.5) : p_params.period;\r
+       //var s:Number;\r
+       //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\r
+       double p = params.size() > 0 ? params[0] : d*0.3*1.5;\r
+       double s;\r
+       double a = params.size() > 1 ? params[1] : 0.0;\r
+       if (a == 0.0 || a < std::abs(c)) \r
+       {\r
+               a = c;\r
+               s = p/4;\r
+       }\r
+       else\r
+               s = p/(2*PI) * std::asin (c/a);\r
+       \r
+       if (t < 1) \r
+               return -.5*(a*std::pow(2,10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )) + b;\r
+\r
+       return a*std::pow(2,-10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )*.5 + c + b;\r
+}\r
+       \r
+double ease_out_in_elastic (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) return ease_out_elastic (t*2, b, c/2, d, params);\r
+       return ease_in_elastic((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_in_back (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\r
+       double s = params.size() > 0 ? params[0] : 1.70158;\r
+       return c*(t/=d)*t*((s+1)*t - s) + b;\r
+}\r
+       \r
+double ease_out_back (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\r
+       double s = params.size() > 0 ? params[0] : 1.70158;\r
+       return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;\r
+}\r
+       \r
+double ease_in_out_back (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\r
+       double s = params.size() > 0 ? params[0] : 1.70158;\r
+       if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;\r
+       return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;\r
+}\r
+       \r
+double ease_out_int_back (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       if (t < d/2) return ease_out_back (t*2, b, c/2, d, params);\r
+       return ease_in_back((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+       \r
+double ease_out_bounce (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if ((t/=d) < (1/2.75))\r
+               return c*(7.5625*t*t) + b;\r
+       else if (t < (2/2.75))\r
+               return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;\r
+       else if (t < (2.5/2.75))\r
+               return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;\r
+       else \r
+               return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;    \r
+}\r
+       \r
+double ease_in_bounce (double t, double b, double c, double d, const std::vector<double>& params)\r
+{\r
+       return c - ease_out_bounce (d-t, 0, c, d, params) + b;\r
+}\r
+\r
+double ease_in_out_bounce (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) return ease_in_bounce (t*2, 0, c, d, params) * .5 + b;\r
+       else return ease_out_bounce (t*2-d, 0, c, d, params) * .5 + c*.5 + b;\r
+}\r
+       \r
+\r
+double ease_out_in_bounce (double t, double b, double c, double d, const std::vector<double>& params) \r
+{\r
+       if (t < d/2) return ease_out_bounce (t*2, b, c/2, d, params);\r
+       return ease_in_bounce((t*2)-d, b+c/2, c/2, d, params);\r
+}\r
+\r
+tweener_t get_tweener(std::wstring name)\r
+{\r
+       std::transform(name.begin(), name.end(), name.begin(), std::tolower);\r
+\r
+       if(name == L"linear")\r
+               return [](double t, double b, double c, double d){return ease_none(t, b, c, d, std::vector<double>());};\r
+       \r
+       std::vector<double> params;\r
+       \r
+       static const boost::wregex expr(L"(?<NAME>\\w*)(:(?<V0>\\d+\\.?\\d?))?(:(?<V1>\\d+\\.?\\d?))?"); // boost::regex has no repeated captures?\r
+       boost::wsmatch what;\r
+       if(boost::regex_match(name, what, expr))\r
+       {\r
+               name = what["NAME"].str();\r
+               if(what["V0"].matched)\r
+                       params.push_back(boost::lexical_cast<double>(what["V0"].str()));\r
+               if(what["V1"].matched)\r
+                       params.push_back(boost::lexical_cast<double>(what["V1"].str()));\r
+       }\r
+               \r
+       typedef std::function<double(double, double, double, double, const std::vector<double>&)> tween_t;      \r
+       static const std::unordered_map<std::wstring, tween_t> tweens = boost::assign::map_list_of      \r
+               (L"",                                   ease_none                  )    \r
+               (L"linear",                             ease_none                  )    \r
+               (L"easenone",                   ease_none                  )\r
+               (L"easeinquad",                 ease_in_quad       )\r
+               (L"easeoutquad",                ease_out_quad      )\r
+               (L"easeinoutquad",              ease_in_out_quad   )\r
+               (L"easeoutinquad",              ease_out_in_quad   )\r
+               (L"easeincubic",                ease_in_cubic      )\r
+               (L"easeoutcubic",               ease_out_cubic     )\r
+               (L"easeinoutcubic",             ease_in_out_cubic  )\r
+               (L"easeoutincubic",             ease_out_in_cubic  )\r
+               (L"easeinquart",                ease_in_quart      )\r
+               (L"easeoutquart",               ease_out_quart     )\r
+               (L"easeinoutquart",             ease_in_out_quart  )\r
+               (L"easeoutinquart",             ease_out_in_quart  )\r
+               (L"easeinquint",                ease_in_quint      )\r
+               (L"easeoutquint",               ease_out_quint     )\r
+               (L"easeinoutquint",             ease_in_out_quint  )\r
+               (L"easeoutinquint",             ease_out_in_quint  )\r
+               (L"easeinsine",                 ease_in_sine       )\r
+               (L"easeoutsine",                ease_out_sine      )\r
+               (L"easeinoutsine",              ease_in_out_sine   )\r
+               (L"easeoutinsine",              ease_out_in_sine   )\r
+               (L"easeinexpo",                 ease_in_expo       )\r
+               (L"easeoutexpo",                ease_out_expo      )\r
+               (L"easeinoutexpo",              ease_in_out_expo   )\r
+               (L"easeoutinexpo",              ease_out_in_expo   )\r
+               (L"easeincirc",                 ease_in_circ       )\r
+               (L"easeoutcirc",                ease_out_circ      )\r
+               (L"easeinoutcirc",              ease_in_out_circ   )\r
+               (L"easeoutincirc",              ease_out_in_circ   )\r
+               (L"easeinelastic",              ease_in_elastic    )\r
+               (L"easeoutelastic",             ease_out_elastic   )\r
+               (L"easeinoutelastic",   ease_in_out_elastic)\r
+               (L"easeoutinelastic",   ease_out_in_elastic)\r
+               (L"easeinback",                 ease_in_back       )\r
+               (L"easeoutback",                ease_out_back      )\r
+               (L"easeinoutback",              ease_in_out_back   )\r
+               (L"easeoutintback",             ease_out_int_back  )\r
+               (L"easeoutbounce",              ease_out_bounce    )\r
+               (L"easeinbounce",               ease_in_bounce     )\r
+               (L"easeinoutbounce",    ease_in_out_bounce )\r
+               (L"easeoutinbounce",    ease_out_in_bounce );\r
+\r
+       auto it = tweens.find(name);\r
+       if(it == tweens.end())\r
+               it = tweens.find(L"linear");\r
+       \r
+       return [=](double t, double b, double c, double d)\r
+       {\r
+               return it->second(t, b, c, d, params);\r
+       };\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/tweener.h b/common/utility/tweener.h
new file mode 100644 (file)
index 0000000..51ec836
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <functional>\r
+\r
+namespace caspar {\r
+\r
+typedef std::function<double(double, double, double, double)> tweener_t;\r
+tweener_t get_tweener(std::wstring name = L"linear");\r
+\r
+}
\ No newline at end of file
diff --git a/common/utility/utf8conv.h b/common/utility/utf8conv.h
new file mode 100644 (file)
index 0000000..8194247
--- /dev/null
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////\r
+//\r
+// FILE: utf8conv.h\r
+//\r
+// Header file defining prototypes of helper functions for converting \r
+// strings between Unicode UTF-8 and UTF-16.\r
+// (The implementation file is "utf8conv_inl.h").\r
+//\r
+// UTF-8 text is stored in std::string; \r
+// UTF-16 text is stored in std::wstring.\r
+//\r
+// This code just uses Win32 Platform SDK and C++ standard library; \r
+// so it can be used also with the Express editions of Visual Studio.\r
+//\r
+//\r
+// Original code: February 4th, 2011\r
+// Last update:   October 15th, 2011\r
+//\r
+// - Added more information to the utf8_conversion_error class\r
+//   (like the return code of ::GetLastError());\r
+//   moreover, the class now derives from std::runtime_error.\r
+//\r
+// - Added conversion function overloads taking raw C strings as input.\r
+//   (This is more efficient when there are raw C strings already\r
+//   available, because it avoids the creation of temporary\r
+//   new std::[w]string's.)\r
+//\r
+// - UTF-8 conversion functions now detect invalid UTF-8 sequences\r
+//   thanks to MB_ERR_INVALID_CHARS flag, and throw an exception\r
+//   in this case.\r
+//\r
+//\r
+// by Giovanni Dicanio <gdicanio@mvps.org>\r
+//\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#pragma once\r
+\r
+\r
+//------------------------------------------------------------------------\r
+//                              INCLUDES\r
+//------------------------------------------------------------------------\r
+\r
+#include <stdexcept>    // std::runtime_error\r
+#include <string>       // STL string classes\r
+\r
+\r
+\r
+namespace utf8util {\r
+\r
+\r
+\r
+//------------------------------------------------------------------------\r
+// Exception class representing an error occurred during UTF-8 conversion.\r
+//------------------------------------------------------------------------\r
+class utf8_conversion_error \r
+    : public std::runtime_error\r
+{\r
+public:\r
+  \r
+    //\r
+    // Naming convention note:\r
+    // -----------------------\r
+    //\r
+    // This exception class is derived from std::runtime_error class,\r
+    // so I chose to use the same naming convention of STL classes\r
+    // (e.g. do_something_intersting() instead of DoSomethingInteresting()).\r
+    //\r
+\r
+\r
+    // Error code type \r
+    // (a DWORD, as the return value type from ::GetLastError())\r
+    typedef unsigned long error_code_type;\r
+\r
+    // Type of conversion\r
+    enum conversion_type\r
+    {\r
+        conversion_utf8_from_utf16,     // UTF-16 ---> UTF-8\r
+        conversion_utf16_from_utf8      // UTF-8  ---> UTF-16\r
+    };\r
+\r
+\r
+    // Constructs an UTF-8 conversion error exception \r
+    // with a raw C string message, conversion type and error code.\r
+    utf8_conversion_error(\r
+        const char * message, \r
+        conversion_type conversion, \r
+        error_code_type error_code\r
+    );\r
+\r
+\r
+    // Constructs an UTF-8 conversion error exception \r
+    // with a std::string message, conversion type and error code.\r
+    utf8_conversion_error(\r
+        const std::string & message, \r
+        conversion_type conversion, \r
+        error_code_type error_code\r
+    );\r
+\r
+\r
+    // Returns the type of conversion (UTF-8 from UTF-16, or vice versa)\r
+    conversion_type conversion() const;\r
+\r
+\r
+    // Returns the error code occurred during the conversion\r
+    // (which is typically the return value of ::GetLastError()).\r
+    error_code_type error_code() const;\r
+\r
+\r
+\r
+    //\r
+    // IMPLEMENTATION\r
+    //\r
+private:\r
+    conversion_type m_conversion;   // kind of conversion\r
+    error_code_type m_error_code;   // error code\r
+};\r
+\r
+//------------------------------------------------------------------------\r
+\r
+\r
+\r
+//------------------------------------------------------------------------\r
+// Converts a string from UTF-8 to UTF-16.\r
+// On error, can throw an utf8_conversion_error exception.\r
+//------------------------------------------------------------------------\r
+std::wstring UTF16FromUTF8(const std::string & utf8);\r
+\r
+\r
+//------------------------------------------------------------------------\r
+// Converts a raw C string from UTF-8 to UTF-16.\r
+// On error, can throw an utf8_conversion_error exception.\r
+// If the input pointer is NULL, an empty string is returned.\r
+//------------------------------------------------------------------------\r
+std::wstring UTF16FromUTF8(const char * utf8);\r
+\r
+\r
+//------------------------------------------------------------------------\r
+// Converts a string from UTF-16 to UTF-8.\r
+// On error, can throw an utf8_conversion_error exception.\r
+//------------------------------------------------------------------------\r
+std::string UTF8FromUTF16(const std::wstring & utf16);\r
+\r
+\r
+//------------------------------------------------------------------------\r
+// Converts a raw C string from UTF-16 to UTF-8.\r
+// On error, can throw an utf8_conversion_error exception.\r
+// If the input pointer is NULL, an empty string is returned.\r
+//------------------------------------------------------------------------\r
+std::string UTF8FromUTF16(const wchar_t * utf16);\r
+\r
+\r
+} // namespace utf8util\r
+\r
+\r
+\r
+#include "utf8conv_inl.h"     // inline implementations\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
diff --git a/common/utility/utf8conv_inl.h b/common/utility/utf8conv_inl.h
new file mode 100644 (file)
index 0000000..234c79d
--- /dev/null
@@ -0,0 +1,368 @@
+//////////////////////////////////////////////////////////////////////////\r
+//\r
+// FILE: utf8conv_inl.h\r
+//\r
+// by Giovanni Dicanio <gdicanio@mvps.org>\r
+//\r
+// Private header file containing implementations of inline functions.\r
+// The public header file for this module is "utf8conv.h"; \r
+// users should *not* #include this private header file directly.\r
+//\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+\r
+#include <string.h>     // strlen()\r
+\r
+#include <Windows.h>    // Win32 Platform SDK main header\r
+\r
+\r
+\r
+namespace utf8util {\r
+\r
+\r
+//------------------------------------------------------------------------\r
+//      Implementation of utf8_conversion_error class methods\r
+//------------------------------------------------------------------------\r
+\r
+inline utf8_conversion_error::utf8_conversion_error(\r
+    const char * message, \r
+    conversion_type conversion, \r
+    error_code_type error_code\r
+    ) : \r
+        std::runtime_error(message),\r
+        m_conversion(conversion),\r
+        m_error_code(error_code)\r
+{\r
+}\r
+\r
+\r
+inline utf8_conversion_error::utf8_conversion_error(\r
+    const std::string & message, \r
+    conversion_type conversion, \r
+    error_code_type error_code\r
+    ) : \r
+        std::runtime_error(message),\r
+        m_conversion(conversion),\r
+        m_error_code(error_code)\r
+{\r
+}\r
+\r
+\r
+inline utf8_conversion_error::conversion_type utf8_conversion_error::conversion() const\r
+{\r
+    return m_conversion;\r
+}\r
+\r
+\r
+inline utf8_conversion_error::error_code_type utf8_conversion_error::error_code() const\r
+{\r
+    return m_error_code;\r
+}\r
+\r
+\r
+\r
+//------------------------------------------------------------------------\r
+//              Implementation of module functions\r
+//------------------------------------------------------------------------\r
+\r
+\r
+inline std::wstring UTF16FromUTF8(const std::string & utf8)\r
+{\r
+    //\r
+    // Special case of empty input string\r
+    //\r
+    if (utf8.empty())\r
+        return std::wstring();\r
+\r
+\r
+    // Fail if an invalid input character is encountered\r
+    const DWORD conversionFlags = MB_ERR_INVALID_CHARS;\r
+\r
+\r
+    //\r
+    // Get length (in wchar_t's) of resulting UTF-16 string\r
+    //\r
+    const int utf16Length = ::MultiByteToWideChar(\r
+        CP_UTF8,            // convert from UTF-8\r
+        conversionFlags,    // flags\r
+        utf8.data(),        // source UTF-8 string\r
+        utf8.length(),      // length (in chars) of source UTF-8 string\r
+        NULL,               // unused - no conversion done in this step\r
+        0                   // request size of destination buffer, in wchar_t's\r
+        );\r
+    if (utf16Length == 0)\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+\r
+        throw utf8_conversion_error(\r
+            (error == ERROR_NO_UNICODE_TRANSLATION) ? \r
+                "Invalid UTF-8 sequence found in input string." :\r
+                "Can't get length of UTF-16 string (MultiByteToWideChar failed).", \r
+            utf8_conversion_error::conversion_utf16_from_utf8,\r
+            error);      \r
+    }\r
+\r
+\r
+    //\r
+    // Allocate destination buffer for UTF-16 string\r
+    //\r
+    std::wstring utf16;\r
+    utf16.resize(utf16Length);\r
+\r
+\r
+    //\r
+    // Do the conversion from UTF-8 to UTF-16\r
+    //\r
+    if ( ! ::MultiByteToWideChar(\r
+        CP_UTF8,            // convert from UTF-8\r
+        0,                  // validation was done in previous call, \r
+                            // so speed up things with default flags\r
+        utf8.data(),        // source UTF-8 string\r
+        utf8.length(),      // length (in chars) of source UTF-8 string\r
+        &utf16[0],          // destination buffer\r
+        utf16.length()      // size of destination buffer, in wchar_t's\r
+        ) )\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar failed).", \r
+            utf8_conversion_error::conversion_utf16_from_utf8,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Return resulting UTF-16 string\r
+    //\r
+    return utf16;\r
+}\r
+\r
+\r
+\r
+inline std::wstring UTF16FromUTF8(const char * utf8)\r
+{\r
+    //\r
+    // Special case of empty input string\r
+    //\r
+    if (utf8 == NULL || *utf8 == '\0')\r
+        return std::wstring();\r
+\r
+\r
+    // Prefetch the length of the input UTF-8 string\r
+    const int utf8Length = static_cast<int>(strlen(utf8));\r
+\r
+    // Fail if an invalid input character is encountered\r
+    const DWORD conversionFlags = MB_ERR_INVALID_CHARS;\r
+\r
+    //\r
+    // Get length (in wchar_t's) of resulting UTF-16 string\r
+    //\r
+    const int utf16Length = ::MultiByteToWideChar(\r
+        CP_UTF8,            // convert from UTF-8\r
+        conversionFlags,    // flags\r
+        utf8,               // source UTF-8 string\r
+        utf8Length,         // length (in chars) of source UTF-8 string\r
+        NULL,               // unused - no conversion done in this step\r
+        0                   // request size of destination buffer, in wchar_t's\r
+        );\r
+    if (utf16Length == 0)\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            (error == ERROR_NO_UNICODE_TRANSLATION) ? \r
+            "Invalid UTF-8 sequence found in input string." :\r
+            "Can't get length of UTF-16 string (MultiByteToWideChar failed).", \r
+            utf8_conversion_error::conversion_utf16_from_utf8,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Allocate destination buffer for UTF-16 string\r
+    //\r
+    std::wstring utf16;\r
+    utf16.resize(utf16Length);\r
+\r
+\r
+    //\r
+    // Do the conversion from UTF-8 to UTF-16\r
+    //\r
+    if ( ! ::MultiByteToWideChar(\r
+        CP_UTF8,            // convert from UTF-8\r
+        0,                  // validation was done in previous call, \r
+                            // so speed up things with default flags\r
+        utf8,               // source UTF-8 string\r
+        utf8Length,         // length (in chars) of source UTF-8 string\r
+        &utf16[0],          // destination buffer\r
+        utf16.length()      // size of destination buffer, in wchar_t's\r
+        ) )\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar failed).", \r
+            utf8_conversion_error::conversion_utf16_from_utf8,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Return resulting UTF-16 string\r
+    //\r
+    return utf16;\r
+}\r
+\r
+\r
+\r
+inline std::string UTF8FromUTF16(const std::wstring & utf16)\r
+{\r
+    //\r
+    // Special case of empty input string\r
+    //\r
+    if (utf16.empty())\r
+        return std::string();\r
+\r
+\r
+    //\r
+    // Get length (in chars) of resulting UTF-8 string\r
+    //\r
+    const int utf8Length = ::WideCharToMultiByte(\r
+        CP_UTF8,            // convert to UTF-8\r
+        0,                  // default flags\r
+        utf16.data(),       // source UTF-16 string\r
+        utf16.length(),     // source string length, in wchar_t's,\r
+        NULL,               // unused - no conversion required in this step\r
+        0,                  // request buffer size\r
+        NULL, NULL          // unused\r
+        );\r
+    if (utf8Length == 0)\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't get length of UTF-8 string (WideCharToMultiByte failed).", \r
+            utf8_conversion_error::conversion_utf8_from_utf16,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Allocate destination buffer for UTF-8 string\r
+    //\r
+    std::string utf8;\r
+    utf8.resize(utf8Length);\r
+\r
+\r
+    //\r
+    // Do the conversion from UTF-16 to UTF-8\r
+    //\r
+    if ( ! ::WideCharToMultiByte(\r
+        CP_UTF8,                // convert to UTF-8\r
+        0,                      // default flags\r
+        utf16.data(),           // source UTF-16 string\r
+        utf16.length(),         // source string length, in wchar_t's,\r
+        &utf8[0],               // destination buffer\r
+        utf8.length(),          // destination buffer size, in chars\r
+        NULL, NULL              // unused\r
+        ) )\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte failed).", \r
+            utf8_conversion_error::conversion_utf8_from_utf16,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Return resulting UTF-8 string\r
+    //\r
+    return utf8;\r
+}\r
+\r
+\r
+\r
+inline std::string UTF8FromUTF16(const wchar_t * utf16)\r
+{\r
+    //\r
+    // Special case of empty input string\r
+    //\r
+    if (utf16 == NULL || *utf16 == L'\0')\r
+        return std::string();\r
+\r
+\r
+    // Prefetch the length of the input UTF-16 string\r
+    const int utf16Length = static_cast<int>(wcslen(utf16));\r
+  \r
+\r
+    //\r
+    // Get length (in chars) of resulting UTF-8 string\r
+    //\r
+    const int utf8Length = ::WideCharToMultiByte(\r
+        CP_UTF8,            // convert to UTF-8\r
+        0,                  // default flags\r
+        utf16,              // source UTF-16 string\r
+        utf16Length,        // source string length, in wchar_t's,\r
+        NULL,               // unused - no conversion required in this step\r
+        0,                  // request buffer size\r
+        NULL, NULL          // unused\r
+        );\r
+    if (utf8Length == 0)\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't get length of UTF-8 string (WideCharToMultiByte failed).", \r
+            utf8_conversion_error::conversion_utf8_from_utf16,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Allocate destination buffer for UTF-8 string\r
+    //\r
+    std::string utf8;\r
+    utf8.resize(utf8Length);\r
+\r
+\r
+    //\r
+    // Do the conversion from UTF-16 to UTF-8\r
+    //\r
+    if ( ! ::WideCharToMultiByte(\r
+        CP_UTF8,                // convert to UTF-8\r
+        0,                      // default flags\r
+        utf16,                  // source UTF-16 string\r
+        utf16Length,            // source string length, in wchar_t's,\r
+        &utf8[0],               // destination buffer\r
+        utf8.length(),          // destination buffer size, in chars\r
+        NULL, NULL              // unused\r
+        ) )\r
+    {\r
+        // Error\r
+        DWORD error = ::GetLastError();\r
+        throw utf8_conversion_error(\r
+            "Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte failed).", \r
+            utf8_conversion_error::conversion_utf8_from_utf16,\r
+            error);\r
+    }\r
+\r
+\r
+    //\r
+    // Return resulting UTF-8 string\r
+    //\r
+    return utf8;\r
+}\r
+\r
+\r
+\r
+} // namespace utf8util\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
diff --git a/core/StdAfx.cpp b/core/StdAfx.cpp
new file mode 100644 (file)
index 0000000..f2b946a
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"
\ No newline at end of file
diff --git a/core/StdAfx.h b/core/StdAfx.h
new file mode 100644 (file)
index 0000000..30a9629
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#define NOMINMAX\r
+\r
+#include <GL/glew.h>\r
+\r
+#include <algorithm>\r
+#include <array>\r
+#include <functional>\r
+#include <deque>\r
+#include <map>\r
+#include <memory>\r
+#include <queue>\r
+#include <string>\r
+#include <vector>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/range/adaptors.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/property_tree/xml_parser.hpp>\r
+\r
+#include <common/utility/string.h>\r
+#include <common/memory/safe_ptr.h>\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include <common/log/log.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/exception/win32_exception.h>\r
+#include <common/utility/assert.h>\r
diff --git a/core/consumer/frame/read_frame.h b/core/consumer/frame/read_frame.h
new file mode 100644 (file)
index 0000000..02369f8
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class read_frame : boost::noncopyable\r
+{\r
+public:\r
+       virtual const boost::iterator_range<const unsigned char*> image_data() const = 0;\r
+       virtual const boost::iterator_range<const short*> audio_data() const = 0;\r
+\r
+       static safe_ptr<const read_frame> empty()\r
+       {\r
+               struct empty : public read_frame\r
+               {                       \r
+                       virtual const boost::iterator_range<const unsigned char*> image_data() const {return boost::iterator_range<const unsigned char*>();}\r
+                       virtual const boost::iterator_range<const short*> audio_data() const {return boost::iterator_range<const short*>();}\r
+               };\r
+               static safe_ptr<const empty> frame;\r
+               return frame;\r
+       }\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/consumer/frame_consumer.cpp b/core/consumer/frame_consumer.cpp
new file mode 100644 (file)
index 0000000..bce2337
--- /dev/null
@@ -0,0 +1,161 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "frame_consumer.h"\r
+\r
+#include <common/env.h>\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/concurrency/future_util.h>\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+\r
+#include <boost/circular_buffer.hpp>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+std::vector<const consumer_factory_t> g_factories;\r
+\r
+void register_consumer_factory(const consumer_factory_t& factory)\r
+{\r
+       g_factories.push_back(factory);\r
+}\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.empty())\r
+               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("params") << arg_value_info(""));\r
+       \r
+       auto consumer = frame_consumer::empty();\r
+       std::any_of(g_factories.begin(), g_factories.end(), [&](const consumer_factory_t& factory) -> bool\r
+               {\r
+                       try\r
+                       {\r
+                               consumer = factory(params);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+                       return consumer != frame_consumer::empty();\r
+               });\r
+\r
+       if(consumer == frame_consumer::empty())\r
+               BOOST_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax."));\r
+\r
+       return consumer;\r
+}\r
+\r
+// This class is used to guarantee that audio cadence is correct. This is important for NTSC audio.\r
+class cadence_guard : public frame_consumer\r
+{\r
+       safe_ptr<frame_consumer>                consumer_;\r
+       std::vector<size_t>                             audio_cadence_;\r
+       boost::circular_buffer<size_t>  sync_buffer_;\r
+public:\r
+       cadence_guard(const safe_ptr<frame_consumer>& consumer)\r
+               : consumer_(consumer)\r
+       {\r
+       }\r
+       \r
+       virtual void initialize(const video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               audio_cadence_  = format_desc.audio_cadence;\r
+               sync_buffer_    = boost::circular_buffer<size_t>(format_desc.audio_cadence.size());\r
+               consumer_->initialize(format_desc, channel_index);\r
+       }\r
+\r
+       virtual boost::unique_future<bool> send(const safe_ptr<read_frame>& frame) override\r
+       {               \r
+               if(audio_cadence_.size() == 1)\r
+                       return consumer_->send(frame);\r
+\r
+               boost::unique_future<bool> result = caspar::wrap_as_future(true);\r
+               \r
+               if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size())) \r
+               {       \r
+                       // Audio sent so far is in sync, now we can send the next chunk.\r
+                       result = consumer_->send(frame);\r
+                       boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+               }\r
+               else\r
+                       CASPAR_LOG(trace) << print() << L" Syncing audio.";\r
+\r
+               sync_buffer_.push_back(static_cast<size_t>(frame->audio_data().size()));\r
+               \r
+               return std::move(result);\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return consumer_->print();\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               return consumer_->info();\r
+       }\r
+\r
+       virtual bool has_synchronization_clock() const override\r
+       {\r
+               return consumer_->has_synchronization_clock();\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return consumer_->buffer_depth();\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return consumer_->index();\r
+       }\r
+};\r
+\r
+safe_ptr<frame_consumer> create_consumer_cadence_guard(const safe_ptr<frame_consumer>& consumer)\r
+{\r
+       return make_safe<cadence_guard>(std::move(consumer));\r
+}\r
+\r
+const safe_ptr<frame_consumer>& frame_consumer::empty()\r
+{\r
+       struct empty_frame_consumer : public frame_consumer\r
+       {\r
+               virtual boost::unique_future<bool> send(const safe_ptr<read_frame>&) override { return caspar::wrap_as_future(false); }\r
+               virtual void initialize(const video_format_desc&, int) override{}\r
+               virtual std::wstring print() const override {return L"empty";}\r
+               virtual bool has_synchronization_clock() const override {return false;}\r
+               virtual size_t buffer_depth() const override {return 0;};\r
+               virtual int index() const{return -1;}\r
+               virtual boost::property_tree::wptree info() const override\r
+               {\r
+                       boost::property_tree::wptree info;\r
+                       info.add(L"type", L"empty-consumer");\r
+                       return info;\r
+               }\r
+       };\r
+       static safe_ptr<frame_consumer> consumer = make_safe<empty_frame_consumer>();\r
+       return consumer;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/consumer/frame_consumer.h b/core/consumer/frame_consumer.h
new file mode 100644 (file)
index 0000000..3577a8e
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <functional>\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class read_frame;\r
+struct video_format_desc;\r
+\r
+struct frame_consumer : boost::noncopyable\r
+{\r
+       virtual ~frame_consumer() {}\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<read_frame>& frame) = 0;\r
+       virtual void initialize(const video_format_desc& format_desc, int channel_index) = 0;\r
+       virtual std::wstring print() const = 0;\r
+       virtual boost::property_tree::wptree info() const = 0;\r
+       virtual bool has_synchronization_clock() const {return true;}\r
+       virtual size_t buffer_depth() const = 0;\r
+       virtual int index() const = 0;\r
+\r
+       static const safe_ptr<frame_consumer>& empty();\r
+};\r
+\r
+safe_ptr<frame_consumer> create_consumer_cadence_guard(const safe_ptr<frame_consumer>& consumer);\r
+\r
+typedef std::function<safe_ptr<core::frame_consumer>(const std::vector<std::wstring>&)> consumer_factory_t;\r
+\r
+void register_consumer_factory(const consumer_factory_t& factory);\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/consumer/output.cpp b/core/consumer/output.cpp
new file mode 100644 (file)
index 0000000..4c3647e
--- /dev/null
@@ -0,0 +1,301 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning (disable : 4244)\r
+#endif\r
+\r
+#include "output.h"\r
+\r
+#include "../video_format.h"\r
+#include "../mixer/gpu/ogl_device.h"\r
+#include "../mixer/read_frame.h"\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/utility/assert.h>\r
+#include <common/utility/timer.h>\r
+#include <common/memory/memshfl.h>\r
+#include <common/env.h>\r
+\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/range/adaptors.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+struct output::implementation\r
+{              \r
+       const int                                                                               channel_index_;\r
+       const safe_ptr<diagnostics::graph>                              graph_;\r
+       boost::timer                                                                    consume_timer_;\r
+\r
+       video_format_desc                                                               format_desc_;\r
+\r
+       std::map<int, safe_ptr<frame_consumer>>                 consumers_;\r
+       \r
+       high_prec_timer                                                                 sync_timer_;\r
+\r
+       boost::circular_buffer<safe_ptr<read_frame>>    frames_;\r
+\r
+       executor                                                                                executor_;\r
+               \r
+public:\r
+       implementation(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index) \r
+               : channel_index_(channel_index)\r
+               , graph_(graph)\r
+               , format_desc_(format_desc)\r
+               , executor_(L"output")\r
+       {\r
+               graph_->set_color("consume-time", diagnostics::color(1.0f, 0.4f, 0.0f, 0.8));\r
+       }       \r
+       \r
+       void add(int index, safe_ptr<frame_consumer> consumer)\r
+       {               \r
+               remove(index);\r
+\r
+               consumer = create_consumer_cadence_guard(consumer);\r
+               consumer->initialize(format_desc_, channel_index_);\r
+\r
+               executor_.invoke([&]\r
+               {\r
+                       consumers_.insert(std::make_pair(index, consumer));\r
+                       CASPAR_LOG(info) << print() << L" " << consumer->print() << L" Added.";\r
+               }, high_priority);\r
+       }\r
+\r
+       void add(const safe_ptr<frame_consumer>& consumer)\r
+       {\r
+               add(consumer->index(), consumer);\r
+       }\r
+\r
+       void remove(int index)\r
+       {               \r
+               // Destroy  consumer on calling thread:\r
+               std::shared_ptr<frame_consumer> old_consumer;\r
+\r
+               executor_.invoke([&]\r
+               {\r
+                       auto it = consumers_.find(index);\r
+                       if(it != consumers_.end())\r
+                       {\r
+                               old_consumer = it->second;\r
+                               consumers_.erase(it);\r
+                       }\r
+               }, high_priority);\r
+\r
+               if(old_consumer)\r
+               {\r
+                       auto str = old_consumer->print();\r
+                       old_consumer.reset();\r
+                       CASPAR_LOG(info) << print() << L" " << str << L" Removed.";\r
+               }\r
+       }\r
+\r
+       void remove(const safe_ptr<frame_consumer>& consumer)\r
+       {\r
+               remove(consumer->index());\r
+       }\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc)\r
+       {\r
+               executor_.invoke([&]\r
+               {\r
+                       auto it = consumers_.begin();\r
+                       while(it != consumers_.end())\r
+                       {                                               \r
+                               try\r
+                               {\r
+                                       it->second->initialize(format_desc, channel_index_);\r
+                                       ++it;\r
+                               }\r
+                               catch(...)\r
+                               {\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                       CASPAR_LOG(info) << print() << L" " << it->second->print() << L" Removed.";\r
+                                       consumers_.erase(it++);\r
+                               }\r
+                       }\r
+                       \r
+                       format_desc_ = format_desc;\r
+                       frames_.clear();\r
+               });\r
+       }\r
+\r
+       std::pair<size_t, size_t> minmax_buffer_depth() const\r
+       {               \r
+               if(consumers_.empty())\r
+                       return std::make_pair(0, 0);\r
+               \r
+               auto buffer_depths = consumers_ | \r
+                                                        boost::adaptors::map_values | // std::function is MSVC workaround\r
+                                                        boost::adaptors::transformed(std::function<int(const safe_ptr<frame_consumer>&)>([](const safe_ptr<frame_consumer>& x){return x->buffer_depth();})); \r
+               \r
+\r
+               return std::make_pair(*boost::range::min_element(buffer_depths), *boost::range::max_element(buffer_depths));\r
+       }\r
+\r
+       bool has_synchronization_clock() const\r
+       {\r
+               return boost::range::count_if(consumers_ | boost::adaptors::map_values, [](const safe_ptr<frame_consumer>& x){return x->has_synchronization_clock();}) > 0;\r
+       }\r
+\r
+       void send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& packet)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       try\r
+                       {\r
+                               consume_timer_.restart();\r
+\r
+                               auto input_frame = packet.first;\r
+\r
+                               if(!has_synchronization_clock())\r
+                                       sync_timer_.tick(1.0/format_desc_.fps);\r
+\r
+                               if(input_frame->image_size() != format_desc_.size)\r
+                               {\r
+                                       sync_timer_.tick(1.0/format_desc_.fps);\r
+                                       return;\r
+                               }\r
+                                       \r
+                               auto minmax = minmax_buffer_depth();\r
+\r
+                               frames_.set_capacity(minmax.second - minmax.first + 1);\r
+                               frames_.push_back(input_frame);\r
+\r
+                               if(!frames_.full())\r
+                                       return;\r
+\r
+                               std::map<int, boost::unique_future<bool>> send_results;\r
+\r
+                               // Start invocations\r
+                               for (auto it = consumers_.begin(); it != consumers_.end(); ++it)\r
+                               {\r
+                                       auto consumer   = it->second;\r
+                                       auto frame              = frames_.at(consumer->buffer_depth()-minmax.first);\r
+                                               \r
+                                       try\r
+                                       {\r
+                                               send_results.insert(std::make_pair(it->first, consumer->send(frame)));\r
+                                       }\r
+                                       catch(...)\r
+                                       {\r
+                                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                               try\r
+                                               {\r
+                                                       send_results.insert(std::make_pair(it->first, consumer->send(frame)));\r
+                                               }\r
+                                               catch(...)\r
+                                               {\r
+                                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                                       CASPAR_LOG(error) << "Failed to recover consumer: " << consumer->print() << L". Removing it.";\r
+                                                       consumers_.erase(it);\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               // Retrieve results\r
+                               for (auto result_it = send_results.begin(); result_it != send_results.end(); ++result_it)\r
+                               {\r
+                                       auto consumer           = consumers_.at(result_it->first);\r
+                                       auto frame                      = frames_.at(consumer->buffer_depth()-minmax.first);\r
+                                       auto& result_future     = result_it->second;\r
+                                               \r
+                                       try\r
+                                       {\r
+                                               if(!result_future.get())\r
+                                               {\r
+                                                       CASPAR_LOG(info) << print() << L" " << consumer->print() << L" Removed.";\r
+                                                       consumers_.erase(result_it->first);\r
+                                               }\r
+                                       }\r
+                                       catch(...)\r
+                                       {\r
+                                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                               try\r
+                                               {\r
+                                                       consumer->initialize(format_desc_, channel_index_);\r
+                                                       if(!consumer->send(frame).get())\r
+                                                       {\r
+                                                               CASPAR_LOG(info) << print() << L" " << consumer->print() << L" Removed.";\r
+                                                               consumers_.erase(result_it->first);\r
+                                                       }\r
+                                               }\r
+                                               catch(...)\r
+                                               {\r
+                                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                                       CASPAR_LOG(error) << "Failed to recover consumer: " << consumer->print() << L". Removing it.";\r
+                                                       consumers_.erase(result_it->first);\r
+                                               }\r
+                                       }\r
+                               }\r
+                                               \r
+                               graph_->set_value("consume-time", consume_timer_.elapsed()*format_desc_.fps*0.5);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+               });\r
+       }\r
+\r
+       std::wstring print() const\r
+       {\r
+               return L"output[" + boost::lexical_cast<std::wstring>(channel_index_) + L"]";\r
+       }\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info()\r
+       {\r
+               return std::move(executor_.begin_invoke([&]() -> boost::property_tree::wptree\r
+               {                       \r
+                       boost::property_tree::wptree info;\r
+                       BOOST_FOREACH(auto& consumer, consumers_)\r
+                       {\r
+                               info.add_child(L"consumers.consumer", consumer.second->info())\r
+                                       .add(L"index", consumer.first); \r
+                       }\r
+                       return info;\r
+               }, high_priority));\r
+       }\r
+\r
+       bool empty()\r
+       {\r
+               return executor_.invoke([this]\r
+               {\r
+                       return consumers_.empty();\r
+               });\r
+       }\r
+};\r
+\r
+output::output(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index) : impl_(new implementation(graph, format_desc, channel_index)){}\r
+void output::add(int index, const safe_ptr<frame_consumer>& consumer){impl_->add(index, consumer);}\r
+void output::add(const safe_ptr<frame_consumer>& consumer){impl_->add(consumer);}\r
+void output::remove(int index){impl_->remove(index);}\r
+void output::remove(const safe_ptr<frame_consumer>& consumer){impl_->remove(consumer);}\r
+void output::send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame) {impl_->send(frame); }\r
+void output::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
+boost::unique_future<boost::property_tree::wptree> output::info() const{return impl_->info();}\r
+bool output::empty() const{return impl_->empty();}\r
+}}
\ No newline at end of file
diff --git a/core/consumer/output.h b/core/consumer/output.h
new file mode 100644 (file)
index 0000000..1336a66
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../consumer/frame_consumer.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/concurrency/target.h>\r
+#include <common/diagnostics/graph.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class output : public target<std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>>\r
+                        , boost::noncopyable\r
+{\r
+public:\r
+       explicit output(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index);\r
+\r
+       // target\r
+       \r
+       virtual void send( const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame) override;\r
+\r
+       // output\r
+       \r
+       void add(const safe_ptr<frame_consumer>& consumer);\r
+       void add(int index, const safe_ptr<frame_consumer>& consumer);\r
+       void remove(const safe_ptr<frame_consumer>& consumer);\r
+       void remove(int index);\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc);\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info() const;\r
+\r
+       bool empty() const;\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/core.vcxproj b/core/core.vcxproj
new file mode 100644 (file)
index 0000000..872801a
--- /dev/null
@@ -0,0 +1,465 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}</ProjectGuid>\r
+    <RootNamespace>Server</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>core</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\;..\dependencies\boost\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\;..\dependencies\boost\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\;..\dependencies\boost\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\;..\dependencies\boost\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>FreeImage.lib;tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>true</GenerateMapFile>\r
+      <MapExports>true</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="mixer\audio\audio_util.h" />\r
+    <ClInclude Include="mixer\gpu\fence.h" />\r
+    <ClInclude Include="mixer\gpu\shader.h" />\r
+    <ClInclude Include="mixer\image\blend_modes.h" />\r
+    <ClInclude Include="mixer\image\shader\blending_glsl.h" />\r
+    <ClInclude Include="mixer\image\shader\image_shader.h" />\r
+    <ClInclude Include="producer\channel\channel_producer.h" />\r
+    <ClInclude Include="producer\playlist\playlist_producer.h" />\r
+    <ClInclude Include="thumbnail_generator.h" />\r
+    <ClInclude Include="video_channel.h" />\r
+    <ClInclude Include="consumer\output.h" />\r
+    <ClInclude Include="consumer\frame_consumer.h" />\r
+    <ClInclude Include="mixer\audio\audio_mixer.h" />\r
+    <ClInclude Include="mixer\mixer.h" />\r
+    <ClInclude Include="mixer\gpu\device_buffer.h" />\r
+    <ClInclude Include="mixer\gpu\host_buffer.h" />\r
+    <ClInclude Include="mixer\gpu\ogl_device.h" />\r
+    <ClInclude Include="mixer\image\image_kernel.h" />\r
+    <ClInclude Include="mixer\image\image_mixer.h" />\r
+    <ClInclude Include="mixer\read_frame.h" />\r
+    <ClInclude Include="mixer\write_frame.h" />\r
+    <ClInclude Include="producer\color\color_producer.h" />\r
+    <ClInclude Include="producer\frame\basic_frame.h" />\r
+    <ClInclude Include="producer\frame\frame_factory.h" />\r
+    <ClInclude Include="producer\frame\frame_visitor.h" />\r
+    <ClInclude Include="producer\frame\frame_transform.h" />\r
+    <ClInclude Include="producer\frame\pixel_format.h" />\r
+    <ClInclude Include="producer\frame_producer.h" />\r
+    <ClInclude Include="producer\stage.h" />\r
+    <ClInclude Include="producer\layer.h" />\r
+    <ClInclude Include="producer\separated\separated_producer.h" />\r
+    <ClInclude Include="producer\transition\transition_producer.h" />\r
+    <ClInclude Include="video_format.h" />\r
+    <CustomBuildStep Include="consumers\bluefish\BluefishException.h" />\r
+    <CustomBuildStep Include="consumers\bluefish\BluefishFrameManager.h" />\r
+    <CustomBuildStep Include="consumers\bluefish\BluefishPlaybackStrategy.h" />\r
+    <CustomBuildStep Include="consumers\bluefish\BlueFishVideoConsumer.h" />\r
+    <CustomBuildStep Include="PlaybackControl.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="mixer\gpu\fence.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\shader.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\blend_modes.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\shader\image_shader.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\channel\channel_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\playlist\playlist_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../stdafx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="thumbnail_generator.cpp" />\r
+    <ClCompile Include="video_channel.cpp" />\r
+    <ClCompile Include="consumer\frame_consumer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\output.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\audio\audio_mixer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\mixer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\ogl_device.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\image_kernel.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\image_mixer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\read_frame.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\write_frame.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\color\color_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame\basic_frame.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame\frame_transform.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\stage.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\layer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreprocessToFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\separated\separated_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\transition\transition_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="video_format.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/core/core.vcxproj.filters b/core/core.vcxproj.filters
new file mode 100644 (file)
index 0000000..1a7f733
--- /dev/null
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{cc341f3a-7ea0-424a-bacd-c40aa8e7822b}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{71accefc-1437-4e1d-9ff7-9de654a32df9}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\transition">\r
+      <UniqueIdentifier>{26bf9811-1954-46f5-86ce-ecdc26e6db16}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\color">\r
+      <UniqueIdentifier>{78b16c14-bf29-4511-9122-684ff513dbf5}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\frame">\r
+      <UniqueIdentifier>{b19721c1-8dd1-45fb-b9e3-212b548ebbb6}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\separated">\r
+      <UniqueIdentifier>{cf834e89-32d6-47bc-8d5a-10e032f88e15}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer">\r
+      <UniqueIdentifier>{e480e128-a351-4dc6-a7ab-f58b480f6afd}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\audio">\r
+      <UniqueIdentifier>{0951ac32-6cd0-4a9f-865d-6f86600f12f8}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\image">\r
+      <UniqueIdentifier>{1cca1d41-f9b1-4b7b-b34f-8a88dcb5b904}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\gpu">\r
+      <UniqueIdentifier>{2d2ae7ff-03d7-4e8c-a298-fb41ee42a885}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{35d7835f-f813-4b4b-8d8d-8a35dfef68d3}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\playlist">\r
+      <UniqueIdentifier>{80ce21ca-5ecd-48c1-97d2-c20ea8e2f2b6}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\image\shader">\r
+      <UniqueIdentifier>{e0a140f8-e217-465c-a934-163b7ea786be}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\channel">\r
+      <UniqueIdentifier>{f2380c6b-6ec8-4a47-8394-357a05eb831a}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="producer\transition\transition_producer.h">\r
+      <Filter>source\producer\transition</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="consumer\frame_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\color\color_producer.h">\r
+      <Filter>source\producer\color</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\layer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame\basic_frame.h">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame\pixel_format.h">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame\frame_visitor.h">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame\frame_factory.h">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\image\image_kernel.h">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\image\image_mixer.h">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\host_buffer.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\ogl_device.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\device_buffer.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\audio\audio_mixer.h">\r
+      <Filter>source\mixer\audio</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\separated\separated_producer.h">\r
+      <Filter>source\producer\separated</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\read_frame.h">\r
+      <Filter>source\mixer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\write_frame.h">\r
+      <Filter>source\mixer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="mixer\mixer.h">\r
+      <Filter>source\mixer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\stage.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="consumer\output.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="video_format.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="video_channel.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\shader.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\fence.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame\frame_transform.h">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\audio\audio_util.h">\r
+      <Filter>source\mixer\audio</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\playlist\playlist_producer.h">\r
+      <Filter>source\producer\playlist</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\image\shader\image_shader.h">\r
+      <Filter>source\mixer\image\shader</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\image\blend_modes.h">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\image\shader\blending_glsl.h">\r
+      <Filter>source\mixer\image\shader</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\channel\channel_producer.h">\r
+      <Filter>source\producer\channel</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="thumbnail_generator.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="producer\transition\transition_producer.cpp">\r
+      <Filter>source\producer\transition</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\frame_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\color\color_producer.cpp">\r
+      <Filter>source\producer\color</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\layer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame\basic_frame.cpp">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\image_mixer.cpp">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\image_kernel.cpp">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\ogl_device.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\audio\audio_mixer.cpp">\r
+      <Filter>source\mixer\audio</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\separated\separated_producer.cpp">\r
+      <Filter>source\producer\separated</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\read_frame.cpp">\r
+      <Filter>source\mixer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\write_frame.cpp">\r
+      <Filter>source\mixer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="mixer\mixer.cpp">\r
+      <Filter>source\mixer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\stage.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\output.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="video_channel.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="video_format.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\shader.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\fence.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame\frame_transform.cpp">\r
+      <Filter>source\producer\frame</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\playlist\playlist_producer.cpp">\r
+      <Filter>source\producer\playlist</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\frame_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\shader\image_shader.cpp">\r
+      <Filter>source\mixer\image\shader</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\image\blend_modes.cpp">\r
+      <Filter>source\mixer\image</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\channel\channel_producer.cpp">\r
+      <Filter>source\producer\channel</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="thumbnail_generator.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/core/mixer/audio/audio_mixer.cpp b/core/mixer/audio/audio_mixer.cpp
new file mode 100644 (file)
index 0000000..eea3057
--- /dev/null
@@ -0,0 +1,221 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "audio_mixer.h"\r
+\r
+#include <core/mixer/write_frame.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <common/diagnostics/graph.h>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+#include <boost/range/adaptors.hpp>\r
+#include <boost/range/distance.hpp>\r
+\r
+#include <map>\r
+#include <stack>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct audio_item\r
+{\r
+       const void*                     tag;\r
+       frame_transform         transform;\r
+       audio_buffer            audio_data;\r
+\r
+       audio_item()\r
+       {\r
+       }\r
+\r
+       audio_item(audio_item&& other)\r
+               : tag(std::move(other.tag))\r
+               , transform(std::move(other.transform))\r
+               , audio_data(std::move(other.audio_data))\r
+       {\r
+       }\r
+};\r
+\r
+typedef std::vector<float, tbb::cache_aligned_allocator<float>> audio_buffer_ps;\r
+       \r
+struct audio_stream\r
+{\r
+       frame_transform         prev_transform;\r
+       audio_buffer_ps         audio_data;\r
+};\r
+\r
+struct audio_mixer::implementation\r
+{\r
+       safe_ptr<diagnostics::graph>            graph_;\r
+       std::stack<core::frame_transform>       transform_stack_;\r
+       std::map<const void*, audio_stream>     audio_streams_;\r
+       std::vector<audio_item>                         items_;\r
+       std::vector<size_t>                                     audio_cadence_;\r
+       video_format_desc                                       format_desc_;\r
+       float                                                           master_volume_;\r
+       float                                                           previous_master_volume_;\r
+       \r
+public:\r
+       implementation(const safe_ptr<diagnostics::graph>& graph)\r
+               : graph_(graph)\r
+               , format_desc_(video_format_desc::get(video_format::invalid))\r
+               , master_volume_(1.0f)\r
+               , previous_master_volume_(master_volume_)\r
+       {\r
+               graph_->set_color("volume", diagnostics::color(1.0f, 0.8f, 0.1f));\r
+               transform_stack_.push(core::frame_transform());\r
+       }\r
+       \r
+       void begin(core::basic_frame& frame)\r
+       {\r
+               transform_stack_.push(transform_stack_.top()*frame.get_frame_transform());\r
+       }\r
+\r
+       void visit(core::write_frame& frame)\r
+       {\r
+               if(transform_stack_.top().volume < 0.002 || frame.audio_data().empty())\r
+                       return;\r
+\r
+               audio_item item;\r
+               item.tag                = frame.tag();\r
+               item.transform  = transform_stack_.top();\r
+               item.audio_data = std::move(frame.audio_data()); // Note: We don't need to care about upper/lower since audio_data is removed/moved from the last field.\r
+               \r
+               items_.push_back(std::move(item));              \r
+       }\r
+\r
+       void begin(const core::frame_transform& transform)\r
+       {\r
+               transform_stack_.push(transform_stack_.top()*transform);\r
+       }\r
+               \r
+       void end()\r
+       {\r
+               transform_stack_.pop();\r
+       }\r
+\r
+       void set_master_volume(float volume)\r
+       {\r
+               master_volume_ = volume;\r
+       }\r
+       \r
+       audio_buffer mix(const video_format_desc& format_desc)\r
+       {       \r
+               if(format_desc_ != format_desc)\r
+               {\r
+                       audio_streams_.clear();\r
+                       audio_cadence_ = format_desc.audio_cadence;\r
+                       format_desc_ = format_desc;\r
+               }               \r
+               \r
+               std::map<const void*, audio_stream>     next_audio_streams;\r
+\r
+               BOOST_FOREACH(auto& item, items_)\r
+               {                       \r
+                       audio_buffer_ps next_audio;\r
+\r
+                       auto next_transform = item.transform;\r
+                       auto prev_transform = next_transform;\r
+\r
+                       const auto it = audio_streams_.find(item.tag);\r
+                       if(it != audio_streams_.end())\r
+                       {       \r
+                               prev_transform  = it->second.prev_transform;\r
+                               next_audio              = std::move(it->second.audio_data);\r
+                       }\r
+\r
+                       if(prev_transform.volume < 0.001 && next_transform.volume < 0.001)\r
+                               continue;\r
+                       \r
+                       const float prev_volume = static_cast<float>(prev_transform.volume) * previous_master_volume_;\r
+                       const float next_volume = static_cast<float>(next_transform.volume) * master_volume_;\r
+                                                                       \r
+                       auto alpha = (next_volume-prev_volume)/static_cast<float>(item.audio_data.size()/format_desc.audio_channels);\r
+                       \r
+                       for(size_t n = 0; n < item.audio_data.size(); ++n)\r
+                       {\r
+                               auto sample_multiplier = (prev_volume + (n/format_desc_.audio_channels) * alpha);\r
+                               next_audio.push_back(item.audio_data[n] * sample_multiplier);\r
+                       }\r
+                                                                               \r
+                       next_audio_streams[item.tag].prev_transform  = std::move(next_transform); // Store all active tags, inactive tags will be removed at the end.\r
+                       next_audio_streams[item.tag].audio_data          = std::move(next_audio);                       \r
+               }\r
+\r
+               previous_master_volume_ = master_volume_;\r
+               items_.clear();\r
+\r
+               audio_streams_ = std::move(next_audio_streams);\r
+               \r
+               if(audio_streams_.empty())              \r
+                       audio_streams_[nullptr].audio_data = audio_buffer_ps(audio_cadence_.front(), 0.0f);\r
+                               \r
+               { // sanity check\r
+\r
+                       auto nb_invalid_streams = boost::count_if(audio_streams_ | boost::adaptors::map_values, [&](const audio_stream& x)\r
+                       {\r
+                               return x.audio_data.size() < audio_cadence_.front();\r
+                       });\r
+\r
+                       if(nb_invalid_streams > 0)              \r
+                               CASPAR_LOG(trace) << "[audio_mixer] Incorrect frame audio cadence detected.";                   \r
+               }\r
+\r
+               std::vector<float> result_ps(audio_cadence_.front(), 0.0f);\r
+\r
+               BOOST_FOREACH(auto& stream, audio_streams_ | boost::adaptors::map_values)\r
+               {\r
+                       //CASPAR_LOG(debug) << stream.audio_data.size() << L" : " << result_ps.size();\r
+\r
+                       if(stream.audio_data.size() < result_ps.size())\r
+                       {\r
+                               stream.audio_data.resize(result_ps.size(), 0.0f);\r
+                               CASPAR_LOG(trace) << L"[audio_mixer] Appended zero samples";\r
+                       }\r
+\r
+                       auto out = boost::range::transform(result_ps, stream.audio_data, std::begin(result_ps), std::plus<float>());\r
+                       stream.audio_data.erase(std::begin(stream.audio_data), std::begin(stream.audio_data) + std::distance(std::begin(result_ps), out));\r
+               }\r
+               \r
+               boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+               \r
+               audio_buffer result;\r
+               result.reserve(result_ps.size());\r
+               boost::range::transform(result_ps, std::back_inserter(result), [](float sample){return static_cast<int32_t>(sample);});         \r
+\r
+               auto max = boost::range::max_element(result);\r
+\r
+               graph_->set_value("volume", static_cast<double>(std::abs(*max))/std::numeric_limits<int32_t>::max());\r
+\r
+               return result;\r
+       }\r
+};\r
+\r
+audio_mixer::audio_mixer(const safe_ptr<diagnostics::graph>& graph) : impl_(new implementation(graph)){}\r
+void audio_mixer::begin(core::basic_frame& frame){impl_->begin(frame);}\r
+void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
+void audio_mixer::end(){impl_->end();}\r
+void audio_mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\r
+audio_buffer audio_mixer::operator()(const video_format_desc& format_desc){return impl_->mix(format_desc);}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/audio/audio_mixer.h b/core/mixer/audio/audio_mixer.h
new file mode 100644 (file)
index 0000000..38134f9
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/producer/frame/frame_visitor.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+#include <vector>\r
+\r
+namespace caspar {\r
+       \r
+namespace diagnostics {\r
+       \r
+class graph;\r
+\r
+}\r
+\r
+namespace core {\r
+\r
+struct video_format_desc;\r
+       \r
+typedef std::vector<int32_t, tbb::cache_aligned_allocator<int32_t>> audio_buffer;\r
+\r
+class audio_mixer : public core::frame_visitor, boost::noncopyable\r
+{\r
+public:\r
+       audio_mixer(const safe_ptr<diagnostics::graph>& graph);\r
+\r
+       virtual void begin(core::basic_frame& frame);\r
+       virtual void visit(core::write_frame& frame);\r
+       virtual void end();\r
+\r
+       void set_master_volume(float volume);\r
+\r
+       audio_buffer operator()(const video_format_desc& format_desc);\r
+       \r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/audio/audio_util.h b/core/mixer/audio/audio_util.h
new file mode 100644 (file)
index 0000000..a24f2cb
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <stdint.h>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+template<typename T>\r
+static std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> audio_32_to_24(const T& audio_data)\r
+{      \r
+       auto size                = std::distance(std::begin(audio_data), std::end(audio_data));\r
+       auto input8              = reinterpret_cast<const int8_t*>(&(*std::begin(audio_data)));\r
+       auto output8     = std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>();\r
+                       \r
+       output8.reserve(size*3);\r
+       for(int n = 0; n < size; ++n)\r
+       {\r
+               output8.push_back(input8[n*4+1]);\r
+               output8.push_back(input8[n*4+2]);\r
+               output8.push_back(input8[n*4+3]);\r
+       }\r
+\r
+       return output8;\r
+}\r
+\r
+template<typename T>\r
+static std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>> audio_32_to_16(const T& audio_data)\r
+{      \r
+       auto size                = std::distance(std::begin(audio_data), std::end(audio_data));\r
+       auto input32     = &(*std::begin(audio_data));\r
+       auto output16    = std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>>();\r
+                       \r
+       output16.reserve(size);\r
+       for(int n = 0; n < size; ++n)\r
+               output16.push_back((input32[n] >> 16) & 0xFFFF);\r
+\r
+       return output16;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/device_buffer.cpp b/core/mixer/gpu/device_buffer.cpp
new file mode 100644 (file)
index 0000000..161cac0
--- /dev/null
@@ -0,0 +1,128 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "device_buffer.h"\r
+\r
+#include "fence.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+#include <tbb/atomic.h>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+static GLenum FORMAT[] = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA};\r
+static GLenum INTERNAL_FORMAT[] = {0, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8};       \r
+\r
+unsigned int format(size_t stride)\r
+{\r
+       return FORMAT[stride];\r
+}\r
+\r
+static tbb::atomic<int> g_total_count;\r
+\r
+struct device_buffer::implementation : boost::noncopyable\r
+{\r
+       GLuint id_;\r
+\r
+       const size_t width_;\r
+       const size_t height_;\r
+       const size_t stride_;\r
+\r
+       fence            fence_;\r
+\r
+public:\r
+       implementation(size_t width, size_t height, size_t stride) \r
+               : width_(width)\r
+               , height_(height)\r
+               , stride_(stride)\r
+       {       \r
+               GL(glGenTextures(1, &id_));\r
+               GL(glBindTexture(GL_TEXTURE_2D, id_));\r
+               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
+               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
+               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
+               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
+               GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
+               GL(glBindTexture(GL_TEXTURE_2D, 0));\r
+               CASPAR_LOG(trace) << "[device_buffer] [" << ++g_total_count << L"] allocated size:" << width*height*stride;     \r
+       }       \r
+\r
+       ~implementation()\r
+       {\r
+               try\r
+               {\r
+                       GL(glDeleteTextures(1, &id_));\r
+                       //CASPAR_LOG(trace) << "[device_buffer] [" << --g_total_count << L"] deallocated size:" << width_*height_*stride_;\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+       \r
+       void bind()\r
+       {\r
+               GL(glBindTexture(GL_TEXTURE_2D, id_));\r
+       }\r
+\r
+       void bind(int index)\r
+       {\r
+               GL(glActiveTexture(GL_TEXTURE0+index));\r
+               bind();\r
+       }\r
+\r
+       void unbind()\r
+       {\r
+               GL(glBindTexture(GL_TEXTURE_2D, 0));\r
+       }\r
+\r
+       void begin_read()\r
+       {\r
+               bind();\r
+               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
+               unbind();\r
+               fence_.set();\r
+       }\r
+       \r
+       bool ready() const\r
+       {\r
+               return fence_.ready();\r
+       }\r
+};\r
+\r
+device_buffer::device_buffer(size_t width, size_t height, size_t stride) : impl_(new implementation(width, height, stride)){}\r
+size_t device_buffer::stride() const { return impl_->stride_; }\r
+size_t device_buffer::width() const { return impl_->width_; }\r
+size_t device_buffer::height() const { return impl_->height_; }\r
+void device_buffer::bind(int index){impl_->bind(index);}\r
+void device_buffer::unbind(){impl_->unbind();}\r
+void device_buffer::begin_read(){impl_->begin_read();}\r
+bool device_buffer::ready() const{return impl_->ready();}\r
+int device_buffer::id() const{ return impl_->id_;}\r
+\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/device_buffer.h b/core/mixer/gpu/device_buffer.h
new file mode 100644 (file)
index 0000000..f924d8b
--- /dev/null
@@ -0,0 +1,57 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <memory>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+class device_buffer : boost::noncopyable\r
+{\r
+public:\r
+       \r
+       size_t stride() const;  \r
+       size_t width() const;\r
+       size_t height() const;\r
+               \r
+       void bind(int index);\r
+       void unbind();\r
+               \r
+       void begin_read();\r
+       bool ready() const;\r
+private:\r
+       friend class ogl_device;\r
+       device_buffer(size_t width, size_t height, size_t stride);\r
+\r
+       int id() const;\r
+\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+       \r
+unsigned int format(size_t stride);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/fence.cpp b/core/mixer/gpu/fence.cpp
new file mode 100644 (file)
index 0000000..286b90a
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../StdAfx.h"\r
+\r
+#include "fence.h"\r
+\r
+#include "ogl_device.h"\r
+\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct fence::implementation\r
+{\r
+       GLsync sync_;\r
+\r
+       implementation() : sync_(0){}\r
+       ~implementation(){glDeleteSync(sync_);}\r
+               \r
+       void set()\r
+       {\r
+               glDeleteSync(sync_);\r
+               sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\r
+       }\r
+\r
+       bool ready() const\r
+       {\r
+               if(!sync_)\r
+                       return true;\r
+\r
+               GLsizei length = 0;\r
+               int values[] = {0};\r
+\r
+               GL(glGetSynciv(sync_, GL_SYNC_STATUS, 1, &length, values));\r
+\r
+               return values[0] == GL_SIGNALED;\r
+       }\r
+\r
+       void wait(ogl_device& ogl)\r
+       {       \r
+               int delay = 0;\r
+               if(!ogl.invoke([this]{return ready();}, high_priority))\r
+               {\r
+                       while(!ogl.invoke([this]{return ready();}, normal_priority) && delay < 20)\r
+                       {\r
+                               delay += 2;\r
+                               Sleep(2);\r
+                       }\r
+               }\r
+               \r
+               static tbb::atomic<size_t> count;\r
+               static tbb::atomic<bool> warned;\r
+               \r
+               if(delay > 2 && ++count > 50)\r
+               {\r
+                       if(!warned.fetch_and_store(true))\r
+                       {\r
+                               CASPAR_LOG(warning) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms. Further warnings are sent to trace log level."\r
+                                                                       << L" You can ignore this warning if you do not notice any problems with output video. This warning is caused by insufficent support or performance of your graphics card for OpenGL based memory transfers. "\r
+                                                                       << L" Please try to update your graphics drivers or update your graphics card, see recommendations on (www.casparcg.com)."\r
+                                                                       << L" Further help is available at (www.casparcg.com/forum).";\r
+                       }\r
+                       else\r
+                               CASPAR_LOG(trace) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms.";\r
+               }\r
+       }\r
+};\r
+       \r
+fence::fence() \r
+{\r
+       static bool log_flag = false;\r
+\r
+       if(GLEW_ARB_sync)\r
+               impl_.reset(new implementation());\r
+       else if(!log_flag)\r
+       {\r
+               CASPAR_LOG(warning) << "[fence] GL_SYNC not supported, running without fences. This might cause performance degradation when running multiple channels and short buffer depth.";\r
+               log_flag = true;\r
+       }\r
+}\r
+\r
+void fence::set() \r
+{\r
+       if(impl_)\r
+               impl_->set();\r
+}\r
+\r
+bool fence::ready() const \r
+{\r
+       return impl_ ? impl_->ready() : true;\r
+}\r
+\r
+void fence::wait(ogl_device& ogl)\r
+{\r
+       if(impl_)\r
+               impl_->wait(ogl);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/fence.h b/core/mixer/gpu/fence.h
new file mode 100644 (file)
index 0000000..f566231
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <memory>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class ogl_device;\r
+\r
+// Used to avoid blocking ogl thread for async operations. \r
+// This is imported when several objects use the same ogl context.\r
+// Based on http://www.opengl.org/registry/specs/ARB/sync.txt.\r
+class fence\r
+{\r
+public:\r
+       fence();\r
+       void set();\r
+       bool ready() const;\r
+       void wait(ogl_device& ogl);\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+\r
+}}\r
diff --git a/core/mixer/gpu/host_buffer.cpp b/core/mixer/gpu/host_buffer.cpp
new file mode 100644 (file)
index 0000000..ee9362c
--- /dev/null
@@ -0,0 +1,152 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "host_buffer.h"\r
+\r
+#include "fence.h"\r
+#include "device_buffer.h"\r
+#include "ogl_device.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+#include <tbb/atomic.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+static tbb::atomic<int> g_w_total_count;\r
+static tbb::atomic<int> g_r_total_count;\r
+                                                                                                                                                                                                                                                                                                                               \r
+struct host_buffer::implementation : boost::noncopyable\r
+{      \r
+       GLuint                  pbo_;\r
+       const size_t    size_;\r
+       void*                   data_;\r
+       GLenum                  usage_;\r
+       GLenum                  target_;\r
+       fence                   fence_;\r
+\r
+public:\r
+       implementation(size_t size, usage_t usage) \r
+               : size_(size)\r
+               , data_(nullptr)\r
+               , pbo_(0)\r
+               , target_(usage == write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)\r
+               , usage_(usage == write_only ? GL_STREAM_DRAW : GL_STREAM_READ)\r
+       {\r
+               GL(glGenBuffers(1, &pbo_));\r
+               GL(glBindBuffer(target_, pbo_));\r
+               if(usage_ != write_only)        \r
+                       GL(glBufferData(target_, size_, NULL, usage_)); \r
+               GL(glBindBuffer(target_, 0));\r
+\r
+               if(!pbo_)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
+\r
+               CASPAR_LOG(trace) << "[host_buffer] [" << ++(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
+       }       \r
+\r
+       ~implementation()\r
+       {\r
+               try\r
+               {\r
+                       GL(glDeleteBuffers(1, &pbo_));\r
+                       //CASPAR_LOG(trace) << "[host_buffer] [" << --(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] deallocated size:" << size_ << " usage: " << (usage_ == write_only ? "write_only" : "read_only");\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+\r
+       void map()\r
+       {\r
+               if(data_)\r
+                       return;\r
+\r
+               if(usage_ == write_only)                        \r
+                       GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
+               \r
+               GL(glBindBuffer(target_, pbo_));\r
+               data_ = GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));  \r
+               GL(glBindBuffer(target_, 0)); \r
+               if(!data_)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target_ OpenGL Pixel Buffer Object."));\r
+       }\r
+\r
+       void wait(ogl_device& ogl)\r
+       {\r
+               fence_.wait(ogl);\r
+       }\r
+\r
+       void unmap()\r
+       {\r
+               if(!data_)\r
+                       return;\r
+               \r
+               GL(glBindBuffer(target_, pbo_));\r
+               GL(glUnmapBuffer(target_));     \r
+               data_ = nullptr;                \r
+               GL(glBindBuffer(target_, 0));\r
+       }\r
+\r
+       void bind()\r
+       {\r
+               GL(glBindBuffer(target_, pbo_));\r
+       }\r
+\r
+       void unbind()\r
+       {\r
+               GL(glBindBuffer(target_, 0));\r
+       }\r
+\r
+       void begin_read(size_t width, size_t height, GLuint format)\r
+       {\r
+               unmap();\r
+               bind();\r
+               GL(glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, NULL));\r
+               unbind();\r
+               fence_.set();\r
+       }\r
+\r
+       bool ready() const\r
+       {\r
+               return fence_.ready();\r
+       }\r
+};\r
+\r
+host_buffer::host_buffer(size_t size, usage_t usage) : impl_(new implementation(size, usage)){}\r
+const void* host_buffer::data() const {return impl_->data_;}\r
+void* host_buffer::data() {return impl_->data_;}\r
+void host_buffer::map(){impl_->map();}\r
+void host_buffer::unmap(){impl_->unmap();}\r
+void host_buffer::bind(){impl_->bind();}\r
+void host_buffer::unbind(){impl_->unbind();}\r
+void host_buffer::begin_read(size_t width, size_t height, GLuint format){impl_->begin_read(width, height, format);}\r
+size_t host_buffer::size() const { return impl_->size_; }\r
+bool host_buffer::ready() const{return impl_->ready();}\r
+void host_buffer::wait(ogl_device& ogl){impl_->wait(ogl);}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/host_buffer.h b/core/mixer/gpu/host_buffer.h
new file mode 100644 (file)
index 0000000..26937e7
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class ogl_device;\r
+               \r
+class host_buffer : boost::noncopyable\r
+{\r
+public:\r
+       enum usage_t\r
+       {\r
+               write_only,\r
+               read_only\r
+       };\r
+       \r
+       const void* data() const;\r
+       void* data();\r
+       size_t size() const;    \r
+       \r
+       void bind();\r
+       void unbind();\r
+\r
+       void map();\r
+       void unmap();\r
+       \r
+       void begin_read(size_t width, size_t height, unsigned int format);\r
+       bool ready() const;\r
+       void wait(ogl_device& ogl);\r
+private:\r
+       friend class ogl_device;\r
+       host_buffer(size_t size, usage_t usage);\r
+\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/ogl_device.cpp b/core/mixer/gpu/ogl_device.cpp
new file mode 100644 (file)
index 0000000..0df165b
--- /dev/null
@@ -0,0 +1,389 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+// TODO: Smart GC\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "ogl_device.h"\r
+\r
+#include "shader.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/assert.h>\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <boost/foreach.hpp>\r
+\r
+#include <gl/glew.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+ogl_device::ogl_device() \r
+       : executor_(L"ogl_device")\r
+       , pattern_(nullptr)\r
+       , attached_texture_(0)\r
+       , attached_fbo_(0)\r
+       , active_shader_(0)\r
+       , read_buffer_(0)\r
+{\r
+       CASPAR_LOG(info) << L"Initializing OpenGL Device.";\r
+\r
+       std::fill(binded_textures_.begin(), binded_textures_.end(), 0);\r
+       std::fill(viewport_.begin(), viewport_.end(), 0);\r
+       std::fill(scissor_.begin(), scissor_.end(), 0);\r
+       std::fill(blend_func_.begin(), blend_func_.end(), 0);\r
+       \r
+       invoke([=]\r
+       {\r
+               context_.reset(new sf::Context());\r
+               context_->SetActive(true);\r
+               \r
+               if (glewInit() != GLEW_OK)\r
+                       BOOST_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize GLEW."));\r
+                                               \r
+               CASPAR_LOG(info) << L"OpenGL " << version();\r
+\r
+               if(!GLEW_VERSION_3_0)\r
+                       BOOST_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Your graphics card does not meet the minimum hardware requirements since it does not support OpenGL 3.0 or higher. CasparCG Server will not be able to continue."));\r
+       \r
+               glGenFramebuffers(1, &fbo_);    \r
+               \r
+               CASPAR_LOG(info) << L"Successfully initialized OpenGL Device.";\r
+       });\r
+}\r
+\r
+ogl_device::~ogl_device()\r
+{\r
+       invoke([=]\r
+       {\r
+               BOOST_FOREACH(auto& pool, device_pools_)\r
+                       pool.clear();\r
+               BOOST_FOREACH(auto& pool, host_pools_)\r
+                       pool.clear();\r
+               glDeleteFramebuffers(1, &fbo_);\r
+       });\r
+}\r
+\r
+safe_ptr<device_buffer> ogl_device::allocate_device_buffer(size_t width, size_t height, size_t stride)\r
+{\r
+       std::shared_ptr<device_buffer> buffer;\r
+       try\r
+       {\r
+               buffer.reset(new device_buffer(width, height, stride));\r
+       }\r
+       catch(...)\r
+       {\r
+               try\r
+               {\r
+                       yield();\r
+                       gc().wait();\r
+                                       \r
+                       // Try again\r
+                       buffer.reset(new device_buffer(width, height, stride));\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG(error) << L"ogl: create_device_buffer failed!";\r
+                       throw;\r
+               }\r
+       }\r
+       return make_safe_ptr(buffer);\r
+}\r
+                               \r
+safe_ptr<device_buffer> ogl_device::create_device_buffer(size_t width, size_t height, size_t stride)\r
+{\r
+       CASPAR_VERIFY(stride > 0 && stride < 5);\r
+       CASPAR_VERIFY(width > 0 && height > 0);\r
+       auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
+       std::shared_ptr<device_buffer> buffer;\r
+       if(!pool->items.try_pop(buffer))                \r
+               buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride);}, high_priority);                   \r
+       \r
+       //++pool->usage_count;\r
+\r
+       return safe_ptr<device_buffer>(buffer.get(), [=](device_buffer*) mutable\r
+       {               \r
+               pool->items.push(buffer);       \r
+       });\r
+}\r
+\r
+safe_ptr<host_buffer> ogl_device::allocate_host_buffer(size_t size, host_buffer::usage_t usage)\r
+{\r
+       std::shared_ptr<host_buffer> buffer;\r
+\r
+       try\r
+       {\r
+               buffer.reset(new host_buffer(size, usage));\r
+               if(usage == host_buffer::write_only)\r
+                       buffer->map();\r
+               else\r
+                       buffer->unmap();                        \r
+       }\r
+       catch(...)\r
+       {\r
+               try\r
+               {\r
+                       yield();\r
+                       gc().wait();\r
+\r
+                       // Try again\r
+                       buffer.reset(new host_buffer(size, usage));\r
+                       if(usage == host_buffer::write_only)\r
+                               buffer->map();\r
+                       else\r
+                               buffer->unmap();        \r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG(error) << L"ogl: create_host_buffer failed!";\r
+                       throw;          \r
+               }\r
+       }\r
+\r
+       return make_safe_ptr(buffer);\r
+}\r
+       \r
+safe_ptr<host_buffer> ogl_device::create_host_buffer(size_t size, host_buffer::usage_t usage)\r
+{\r
+       CASPAR_VERIFY(usage == host_buffer::write_only || usage == host_buffer::read_only);\r
+       CASPAR_VERIFY(size > 0);\r
+       auto& pool = host_pools_[usage][size];\r
+       std::shared_ptr<host_buffer> buffer;\r
+       if(!pool->items.try_pop(buffer))        \r
+               buffer = executor_.invoke([=]{return allocate_host_buffer(size, usage);}, high_priority);       \r
+       \r
+       //++pool->usage_count;\r
+\r
+       auto self = shared_from_this();\r
+       return safe_ptr<host_buffer>(buffer.get(), [=](host_buffer*) mutable\r
+       {\r
+               self->executor_.begin_invoke([=]() mutable\r
+               {               \r
+                       if(usage == host_buffer::write_only)\r
+                               buffer->map();\r
+                       else\r
+                               buffer->unmap();\r
+\r
+                       pool->items.push(buffer);\r
+               }, high_priority);      \r
+       });\r
+}\r
+\r
+safe_ptr<ogl_device> ogl_device::create()\r
+{\r
+       return safe_ptr<ogl_device>(new ogl_device());\r
+}\r
+\r
+//template<typename T>\r
+//void flush_pool(buffer_pool<T>& pool)\r
+//{    \r
+//     if(pool.flush_count.fetch_and_increment() < 16)\r
+//             return;\r
+//\r
+//     if(pool.usage_count.fetch_and_store(0) < pool.items.size())\r
+//     {\r
+//             std::shared_ptr<T> buffer;\r
+//             pool.items.try_pop(buffer);\r
+//     }\r
+//\r
+//     pool.flush_count = 0;\r
+//     pool.usage_count = 0;\r
+//}\r
+\r
+void ogl_device::flush()\r
+{\r
+       GL(glFlush());  \r
+               \r
+       //try\r
+       //{\r
+       //      BOOST_FOREACH(auto& pools, device_pools_)\r
+       //      {\r
+       //              BOOST_FOREACH(auto& pool, pools)\r
+       //                      flush_pool(*pool.second);\r
+       //      }\r
+       //      BOOST_FOREACH(auto& pools, host_pools_)\r
+       //      {\r
+       //              BOOST_FOREACH(auto& pool, pools)\r
+       //                      flush_pool(*pool.second);\r
+       //      }\r
+       //}\r
+       //catch(...)\r
+       //{\r
+       //      CASPAR_LOG_CURRENT_EXCEPTION();\r
+       //}\r
+}\r
+\r
+void ogl_device::yield()\r
+{\r
+       executor_.yield();\r
+}\r
+\r
+boost::unique_future<void> ogl_device::gc()\r
+{      \r
+       return begin_invoke([=]\r
+       {\r
+               CASPAR_LOG(info) << " ogl: Running GC.";                \r
+       \r
+               try\r
+               {\r
+                       BOOST_FOREACH(auto& pools, device_pools_)\r
+                       {\r
+                               BOOST_FOREACH(auto& pool, pools)\r
+                                       pool.second->items.clear();\r
+                       }\r
+                       BOOST_FOREACH(auto& pools, host_pools_)\r
+                       {\r
+                               BOOST_FOREACH(auto& pool, pools)\r
+                                       pool.second->items.clear();\r
+                       }\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }, high_priority);\r
+}\r
+\r
+std::wstring ogl_device::version()\r
+{      \r
+       static std::wstring ver = L"Not found";\r
+       try\r
+       {\r
+               ver = widen(invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VERSION)));})\r
+               + " "   + invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));}));                      \r
+       }\r
+       catch(...){}\r
+\r
+       return ver;\r
+}\r
+\r
+\r
+void ogl_device::enable(GLenum cap)\r
+{\r
+       auto& val = caps_[cap];\r
+       if(!val)\r
+       {\r
+               glEnable(cap);\r
+               val = true;\r
+       }\r
+}\r
+\r
+void ogl_device::disable(GLenum cap)\r
+{\r
+       auto& val = caps_[cap];\r
+       if(val)\r
+       {\r
+               glDisable(cap);\r
+               val = false;\r
+       }\r
+}\r
+\r
+void ogl_device::viewport(size_t x, size_t y, size_t width, size_t height)\r
+{\r
+       if(x != viewport_[0] || y != viewport_[1] || width != viewport_[2] || height != viewport_[3])\r
+       {               \r
+               glViewport(x, y, width, height);\r
+               viewport_[0] = x;\r
+               viewport_[1] = y;\r
+               viewport_[2] = width;\r
+               viewport_[3] = height;\r
+       }\r
+}\r
+\r
+void ogl_device::scissor(size_t x, size_t y, size_t width, size_t height)\r
+{\r
+       if(x != scissor_[0] || y != scissor_[1] || width != scissor_[2] || height != scissor_[3])\r
+       {               \r
+               glScissor(x, y, width, height);\r
+               scissor_[0] = x;\r
+               scissor_[1] = y;\r
+               scissor_[2] = width;\r
+               scissor_[3] = height;\r
+       }\r
+}\r
+\r
+void ogl_device::stipple_pattern(const GLubyte* pattern)\r
+{\r
+       if(pattern_ != pattern)\r
+       {               \r
+               glPolygonStipple(pattern);\r
+               pattern_ = pattern;\r
+       }\r
+}\r
+\r
+void ogl_device::attach(device_buffer& texture)\r
+{      \r
+       if(attached_texture_ != texture.id())\r
+       {\r
+               if(attached_fbo_ != fbo_)\r
+               {\r
+                       glBindFramebuffer(GL_FRAMEBUFFER, fbo_);\r
+                       attached_fbo_ = fbo_;\r
+               }\r
+\r
+               GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, texture.id(), 0));\r
+               attached_texture_ = texture.id();\r
+       }\r
+}\r
+\r
+void ogl_device::clear(device_buffer& texture)\r
+{      \r
+       attach(texture);\r
+       GL(glClear(GL_COLOR_BUFFER_BIT));\r
+}\r
+\r
+void ogl_device::read_buffer(device_buffer&)\r
+{\r
+       if(read_buffer_ != GL_COLOR_ATTACHMENT0)\r
+       {\r
+               GL(glReadBuffer(GL_COLOR_ATTACHMENT0));\r
+               read_buffer_ = GL_COLOR_ATTACHMENT0;\r
+       }\r
+}\r
+\r
+void ogl_device::use(shader& shader)\r
+{\r
+       if(active_shader_ != shader.id())\r
+       {               \r
+               GL(glUseProgramObjectARB(shader.id())); \r
+               active_shader_ = shader.id();\r
+       }\r
+}\r
+\r
+void ogl_device::blend_func(int c1, int c2, int a1, int a2)\r
+{\r
+       std::array<int, 4> func = {c1, c2, a1, a2};\r
+\r
+       if(blend_func_ != func)\r
+       {\r
+               blend_func_ = func;\r
+               GL(glBlendFuncSeparate(c1, c2, a1, a2));\r
+       }\r
+}\r
+\r
+void ogl_device::blend_func(int c1, int c2)\r
+{\r
+       blend_func(c1, c2, c1, c2);\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/mixer/gpu/ogl_device.h b/core/mixer/gpu/ogl_device.h
new file mode 100644 (file)
index 0000000..d05c373
--- /dev/null
@@ -0,0 +1,133 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "host_buffer.h"\r
+#include "device_buffer.h"\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+#include <SFML/Window/Context.hpp>\r
+\r
+#include <tbb/concurrent_unordered_map.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <array>\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class shader;\r
+\r
+template<typename T>\r
+struct buffer_pool\r
+{\r
+       tbb::atomic<int> usage_count;\r
+       tbb::atomic<int> flush_count;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<T>> items;\r
+\r
+       buffer_pool()\r
+       {\r
+               usage_count = 0;\r
+               flush_count = 0;\r
+       }\r
+};\r
+\r
+class ogl_device : public std::enable_shared_from_this<ogl_device>, boost::noncopyable\r
+{      \r
+       std::unordered_map<GLenum, bool> caps_;\r
+       std::array<size_t, 4>                    viewport_;\r
+       std::array<size_t, 4>                    scissor_;\r
+       const GLubyte*                                   pattern_;\r
+       GLint                                                    attached_texture_;\r
+       GLuint                                                   attached_fbo_;\r
+       GLint                                                    active_shader_;\r
+       std::array<GLint, 16>                    binded_textures_;\r
+       std::array<GLint, 4>                     blend_func_;\r
+       GLenum                                                   read_buffer_;\r
+\r
+       std::unique_ptr<sf::Context> context_;\r
+       \r
+       std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<buffer_pool<device_buffer>>>, 4> device_pools_;\r
+       std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<buffer_pool<host_buffer>>>, 2> host_pools_;\r
+       \r
+       GLuint fbo_;\r
+\r
+       executor executor_;\r
+                               \r
+       ogl_device();\r
+public:                \r
+       static safe_ptr<ogl_device> create();\r
+       ~ogl_device();\r
+\r
+       // Not thread-safe, must be called inside of context\r
+       void enable(GLenum cap);\r
+       void disable(GLenum cap);\r
+       void viewport(size_t x, size_t y, size_t width, size_t height);\r
+       void scissor(size_t x, size_t y, size_t width, size_t height);\r
+       void stipple_pattern(const GLubyte* pattern);\r
+\r
+       void attach(device_buffer& texture);\r
+       void clear(device_buffer& texture);\r
+       \r
+       void blend_func(int c1, int c2, int a1, int a2);\r
+       void blend_func(int c1, int c2);\r
+       \r
+       void use(shader& shader);\r
+\r
+       void read_buffer(device_buffer& texture);\r
+\r
+       void flush();\r
+\r
+       // thread-afe\r
+       template<typename Func>\r
+       auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
+       {                       \r
+               return executor_.begin_invoke(std::forward<Func>(func), priority);\r
+       }\r
+       \r
+       template<typename Func>\r
+       auto invoke(Func&& func, task_priority priority = normal_priority) -> decltype(func())\r
+       {\r
+               return executor_.invoke(std::forward<Func>(func), priority);\r
+       }\r
+               \r
+       safe_ptr<device_buffer> create_device_buffer(size_t width, size_t height, size_t stride);\r
+       safe_ptr<host_buffer> create_host_buffer(size_t size, host_buffer::usage_t usage);\r
+       \r
+       void yield();\r
+       boost::unique_future<void> gc();\r
+\r
+       std::wstring version();\r
+\r
+private:\r
+       safe_ptr<device_buffer> allocate_device_buffer(size_t width, size_t height, size_t stride);\r
+       safe_ptr<host_buffer> allocate_host_buffer(size_t size, host_buffer::usage_t usage);\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/shader.cpp b/core/mixer/gpu/shader.cpp
new file mode 100644 (file)
index 0000000..ffd20de
--- /dev/null
@@ -0,0 +1,145 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../../stdafx.h"\r
+\r
+#include "shader.h"\r
+\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct shader::implementation : boost::noncopyable\r
+{\r
+       GLuint program_;\r
+       std::unordered_map<std::string, GLint> locations_;\r
+public:\r
+\r
+       implementation(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0)\r
+       {\r
+               GLint success;\r
+       \r
+               const char* vertex_source = vertex_source_str.c_str();\r
+                                               \r
+               auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
+                                       \r
+               GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
+               GL(glCompileShaderARB(vertex_shader));\r
+\r
+               GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+               if (success == GL_FALSE)\r
+               {\r
+                       char info[2048];\r
+                       GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\r
+                       GL(glDeleteObjectARB(vertex_shader));\r
+                       std::stringstream str;\r
+                       str << "Failed to compile vertex shader:" << std::endl << info << std::endl;\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+               }\r
+                       \r
+               const char* fragment_source = fragment_source_str.c_str();\r
+                                               \r
+               auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
+                                       \r
+               GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
+               GL(glCompileShaderARB(fragmemt_shader));\r
+\r
+               GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+               if (success == GL_FALSE)\r
+               {\r
+                       char info[2048];\r
+                       GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info));\r
+                       GL(glDeleteObjectARB(fragmemt_shader));\r
+                       std::stringstream str;\r
+                       str << "Failed to compile fragment shader:" << std::endl << info << std::endl;\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+               }\r
+                       \r
+               program_ = glCreateProgramObjectARB();\r
+                       \r
+               GL(glAttachObjectARB(program_, vertex_shader));\r
+               GL(glAttachObjectARB(program_, fragmemt_shader));\r
+\r
+               GL(glLinkProgramARB(program_));\r
+                       \r
+               GL(glDeleteObjectARB(vertex_shader));\r
+               GL(glDeleteObjectARB(fragmemt_shader));\r
+\r
+               GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
+               if (success == GL_FALSE)\r
+               {\r
+                       char info[2048];\r
+                       GL(glGetInfoLogARB(program_, sizeof(info), 0, info));\r
+                       GL(glDeleteObjectARB(program_));\r
+                       std::stringstream str;\r
+                       str << "Failed to link shader program:" << std::endl << info << std::endl;\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+               }\r
+               GL(glUseProgramObjectARB(program_));\r
+       }\r
+       \r
+       ~implementation()\r
+       {\r
+               glDeleteProgram(program_);\r
+       }\r
+\r
+       GLint get_location(const char* name)\r
+       {\r
+               auto it = locations_.find(name);\r
+               if(it == locations_.end())\r
+                       it = locations_.insert(std::make_pair(name, glGetUniformLocation(program_, name))).first;\r
+               return it->second;\r
+       }\r
+       \r
+       void set(const std::string& name, bool value)\r
+       {\r
+               set(name, value ? 1 : 0);\r
+       }\r
+\r
+       void set(const std::string& name, int value)\r
+       {\r
+               GL(glUniform1i(get_location(name.c_str()), value));\r
+       }\r
+       \r
+       void set(const std::string& name, float value)\r
+       {\r
+               GL(glUniform1f(get_location(name.c_str()), value));\r
+       }\r
+\r
+       void set(const std::string& name, double value)\r
+       {\r
+               GL(glUniform1f(get_location(name.c_str()), static_cast<float>(value)));\r
+       }\r
+};\r
+\r
+\r
+shader::shader(const std::string& vertex_source_str, const std::string& fragment_source_str) : impl_(new implementation(vertex_source_str, fragment_source_str)){}\r
+void shader::set(const std::string& name, bool value){impl_->set(name, value);}\r
+void shader::set(const std::string& name, int value){impl_->set(name, value);}\r
+void shader::set(const std::string& name, float value){impl_->set(name, value);}\r
+void shader::set(const std::string& name, double value){impl_->set(name, value);}\r
+int shader::id() const{return impl_->program_;}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/gpu/shader.h b/core/mixer/gpu/shader.h
new file mode 100644 (file)
index 0000000..4be183b
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+class shader : boost::noncopyable\r
+{\r
+public:\r
+       shader(const std::string& vertex_source_str, const std::string& fragment_source_str);\r
+       void set(const std::string& name, bool value);\r
+       void set(const std::string& name, int value);\r
+       void set(const std::string& name, float value);\r
+       void set(const std::string& name, double value);\r
+private:\r
+       friend class ogl_device;\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+\r
+       int id() const;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/blend_modes.cpp b/core/mixer/image/blend_modes.cpp
new file mode 100644 (file)
index 0000000..340a2b4
--- /dev/null
@@ -0,0 +1,94 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../StdAfx.h"\r
+\r
+#include "blend_modes.h"\r
+\r
+#include <boost/algorithm/string.hpp>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+blend_mode::type get_blend_mode(const std::wstring& str)\r
+{\r
+       if(boost::iequals(str, L"normal"))\r
+               return blend_mode::normal;\r
+       else if(boost::iequals(str, L"lighten"))\r
+               return blend_mode::lighten;\r
+       else if(boost::iequals(str, L"darken"))\r
+               return blend_mode::darken;\r
+       else if(boost::iequals(str, L"multiply"))\r
+               return blend_mode::multiply;\r
+       else if(boost::iequals(str, L"average"))\r
+               return blend_mode::average;\r
+       else if(boost::iequals(str, L"add"))\r
+               return blend_mode::add;\r
+       else if(boost::iequals(str, L"subtract"))\r
+               return blend_mode::subtract;\r
+       else if(boost::iequals(str, L"difference"))\r
+               return blend_mode::difference;\r
+       else if(boost::iequals(str, L"negation"))\r
+               return blend_mode::negation;\r
+       else if(boost::iequals(str, L"exclusion"))\r
+               return blend_mode::exclusion;\r
+       else if(boost::iequals(str, L"screen"))\r
+               return blend_mode::screen;\r
+       else if(boost::iequals(str, L"overlay"))\r
+               return blend_mode::overlay;\r
+       else if(boost::iequals(str, L"soft_light"))\r
+               return blend_mode::soft_light;\r
+       else if(boost::iequals(str, L"hard_light"))\r
+               return blend_mode::hard_light;\r
+       else if(boost::iequals(str, L"color_dodge"))\r
+               return blend_mode::color_dodge;\r
+       else if(boost::iequals(str, L"color_burn"))\r
+               return blend_mode::color_burn;\r
+       else if(boost::iequals(str, L"linear_dodge"))\r
+               return blend_mode::linear_dodge;\r
+       else if(boost::iequals(str, L"linear_burn"))\r
+               return blend_mode::linear_burn;\r
+       else if(boost::iequals(str, L"linear_light"))\r
+               return blend_mode::linear_light;\r
+       else if(boost::iequals(str, L"vivid_light"))\r
+               return blend_mode::vivid_light;\r
+       else if(boost::iequals(str, L"pin_light"))\r
+               return blend_mode::pin_light;\r
+       else if(boost::iequals(str, L"hard_mix"))\r
+               return blend_mode::hard_mix;\r
+       else if(boost::iequals(str, L"reflect"))\r
+               return blend_mode::reflect;\r
+       else if(boost::iequals(str, L"glow"))\r
+               return blend_mode::glow;\r
+       else if(boost::iequals(str, L"phoenix"))\r
+               return blend_mode::phoenix;\r
+       else if(boost::iequals(str, L"contrast"))\r
+               return blend_mode::contrast;\r
+       else if(boost::iequals(str, L"saturation"))\r
+               return blend_mode::saturation;\r
+       else if(boost::iequals(str, L"color"))\r
+               return blend_mode::color;\r
+       else if(boost::iequals(str, L"luminosity"))\r
+               return blend_mode::luminosity;\r
+               \r
+       return blend_mode::normal;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/blend_modes.h b/core/mixer/image/blend_modes.h
new file mode 100644 (file)
index 0000000..6690ee8
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar { namespace core {\r
+               \r
+struct blend_mode\r
+{\r
+       enum type \r
+       {\r
+               normal = 0,\r
+               lighten,\r
+               darken,\r
+               multiply,\r
+               average,\r
+               add,\r
+               subtract,\r
+               difference,\r
+               negation,\r
+               exclusion,\r
+               screen,\r
+               overlay,\r
+               soft_light,\r
+               hard_light,\r
+               color_dodge,\r
+               color_burn,\r
+               linear_dodge,\r
+               linear_burn,\r
+               linear_light,\r
+               vivid_light,\r
+               pin_light,\r
+               hard_mix,\r
+               reflect,\r
+               glow,\r
+               phoenix,\r
+               contrast,\r
+               saturation,\r
+               color,\r
+               luminosity,\r
+               mix,\r
+               blend_mode_count \r
+       };\r
+};\r
+\r
+blend_mode::type get_blend_mode(const std::wstring& str);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/image_kernel.cpp b/core/mixer/image/image_kernel.cpp
new file mode 100644 (file)
index 0000000..f7e837b
--- /dev/null
@@ -0,0 +1,242 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "image_kernel.h"\r
+\r
+#include "shader/image_shader.h"\r
+#include "shader/blending_glsl.h"\r
+\r
+#include "../gpu/shader.h"\r
+#include "../gpu/device_buffer.h"\r
+#include "../gpu/ogl_device.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/gl/gl_check.h>\r
+#include <common/env.h>\r
+\r
+#include <core/video_format.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+GLubyte upper_pattern[] = {\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
+               \r
+GLubyte lower_pattern[] = {\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
+\r
+struct image_kernel::implementation : boost::noncopyable\r
+{      \r
+       safe_ptr<ogl_device>    ogl_;\r
+       safe_ptr<shader>                shader_;\r
+       bool                                    blend_modes_;\r
+                                                       \r
+       implementation(const safe_ptr<ogl_device>& ogl)\r
+               : ogl_(ogl)\r
+               , shader_(ogl_->invoke([&]{return get_image_shader(*ogl, blend_modes_);}))\r
+       {\r
+       }\r
+\r
+       void draw(draw_params&& params)\r
+       {\r
+               static const double epsilon = 0.001;\r
+\r
+               CASPAR_ASSERT(params.pix_desc.planes.size() == params.textures.size());\r
+\r
+               if(params.textures.empty() || !params.background)\r
+                       return;\r
+\r
+               if(params.transform.opacity < epsilon)\r
+                       return;\r
+               \r
+               if(!std::all_of(params.textures.begin(), params.textures.end(), std::mem_fn(&device_buffer::ready)))\r
+               {\r
+                       CASPAR_LOG(trace) << L"[image_mixer] Performance warning. Host to device transfer not complete, GPU will be stalled";\r
+                       ogl_->yield(); // Try to give it some more time.\r
+               }               \r
+               \r
+               // Bind textures\r
+\r
+               for(size_t n = 0; n < params.textures.size(); ++n)\r
+                       params.textures[n]->bind(n);\r
+\r
+               if(params.local_key)\r
+                       params.local_key->bind(texture_id::local_key);\r
+               \r
+               if(params.layer_key)\r
+                       params.layer_key->bind(texture_id::layer_key);\r
+                       \r
+               // Setup shader\r
+                                                               \r
+               ogl_->use(*shader_);\r
+\r
+               shader_->set("plane[0]",                texture_id::plane0);\r
+               shader_->set("plane[1]",                texture_id::plane1);\r
+               shader_->set("plane[2]",                texture_id::plane2);\r
+               shader_->set("plane[3]",                texture_id::plane3);\r
+               shader_->set("local_key",               texture_id::local_key);\r
+               shader_->set("layer_key",               texture_id::layer_key);\r
+               shader_->set("is_hd",                   params.pix_desc.planes.at(0).height > 700 ? 1 : 0);\r
+               shader_->set("has_local_key",   params.local_key);\r
+               shader_->set("has_layer_key",   params.layer_key);\r
+               shader_->set("pixel_format",    params.pix_desc.pix_fmt);       \r
+               shader_->set("opacity",                 params.transform.is_key ? 1.0 : params.transform.opacity);      \r
+               \r
+               // Setup blend_func\r
+               \r
+               if(params.transform.is_key)\r
+                       params.blend_mode = blend_mode::normal;\r
+\r
+               if(blend_modes_)\r
+               {\r
+                       params.background->bind(6);\r
+\r
+                       shader_->set("background",      texture_id::background);\r
+                       shader_->set("blend_mode",      params.blend_mode);\r
+                       shader_->set("keyer",           params.keyer);\r
+               }\r
+               else\r
+               {\r
+                       switch(params.keyer)\r
+                       {\r
+                       case keyer::additive:\r
+                               ogl_->blend_func(GL_ONE, GL_ONE);       \r
+                               break;\r
+                       case keyer::linear:\r
+                       default:                                \r
+                               ogl_->blend_func(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);       \r
+                       }               \r
+               }\r
+\r
+               // Setup image-adjustements\r
+               \r
+               if(params.transform.levels.min_input  > epsilon         ||\r
+                  params.transform.levels.max_input  < 1.0-epsilon     ||\r
+                  params.transform.levels.min_output > epsilon         ||\r
+                  params.transform.levels.max_output < 1.0-epsilon     ||\r
+                  std::abs(params.transform.levels.gamma - 1.0) > epsilon)\r
+               {\r
+                       shader_->set("levels", true);   \r
+                       shader_->set("min_input",       params.transform.levels.min_input);     \r
+                       shader_->set("max_input",       params.transform.levels.max_input);\r
+                       shader_->set("min_output",      params.transform.levels.min_output);\r
+                       shader_->set("max_output",      params.transform.levels.max_output);\r
+                       shader_->set("gamma",           params.transform.levels.gamma);\r
+               }\r
+               else\r
+                       shader_->set("levels", false);  \r
+\r
+               if(std::abs(params.transform.brightness - 1.0) > epsilon ||\r
+                  std::abs(params.transform.saturation - 1.0) > epsilon ||\r
+                  std::abs(params.transform.contrast - 1.0)   > epsilon)\r
+               {\r
+                       shader_->set("csb",     true);  \r
+                       \r
+                       shader_->set("brt", params.transform.brightness);       \r
+                       shader_->set("sat", params.transform.saturation);\r
+                       shader_->set("con", params.transform.contrast);\r
+               }\r
+               else\r
+                       shader_->set("csb",     false); \r
+               \r
+               // Setup interlacing\r
+\r
+               if(params.transform.field_mode == core::field_mode::progressive)                        \r
+                       ogl_->disable(GL_POLYGON_STIPPLE);                      \r
+               else                    \r
+               {\r
+                       ogl_->enable(GL_POLYGON_STIPPLE);\r
+\r
+                       if(params.transform.field_mode == core::field_mode::upper)\r
+                               ogl_->stipple_pattern(upper_pattern);\r
+                       else if(params.transform.field_mode == core::field_mode::lower)\r
+                               ogl_->stipple_pattern(lower_pattern);\r
+               }\r
+\r
+               // Setup drawing area\r
+               \r
+               ogl_->viewport(0, 0, params.background->width(), params.background->height());\r
+                                                               \r
+               auto m_p = params.transform.clip_translation;\r
+               auto m_s = params.transform.clip_scale;\r
+\r
+               bool scissor = m_p[0] > std::numeric_limits<double>::epsilon()                  || m_p[1] > std::numeric_limits<double>::epsilon() ||\r
+                                          m_s[0] < (1.0 - std::numeric_limits<double>::epsilon())      || m_s[1] < (1.0 - std::numeric_limits<double>::epsilon());\r
+\r
+               if(scissor)\r
+               {\r
+                       double w = static_cast<double>(params.background->width());\r
+                       double h = static_cast<double>(params.background->height());\r
+               \r
+                       ogl_->enable(GL_SCISSOR_TEST);\r
+                       ogl_->scissor(static_cast<size_t>(m_p[0]*w), static_cast<size_t>(m_p[1]*h), static_cast<size_t>(m_s[0]*w), static_cast<size_t>(m_s[1]*h));\r
+               }\r
+\r
+               auto f_p = params.transform.fill_translation;\r
+               auto f_s = params.transform.fill_scale;\r
+               \r
+               // Set render target\r
+               \r
+               ogl_->attach(*params.background);\r
+               \r
+               // Draw\r
+                               \r
+               glBegin(GL_QUADS);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 0.0, 0.0); glMultiTexCoord2d(GL_TEXTURE1,  f_p[0]        ,  f_p[1]        );             glVertex2d( f_p[0]        *2.0-1.0,  f_p[1]        *2.0-1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 1.0, 0.0); glMultiTexCoord2d(GL_TEXTURE1, (f_p[0]+f_s[0]),  f_p[1]        );             glVertex2d((f_p[0]+f_s[0])*2.0-1.0,  f_p[1]        *2.0-1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 1.0, 1.0); glMultiTexCoord2d(GL_TEXTURE1, (f_p[0]+f_s[0]), (f_p[1]+f_s[1]));             glVertex2d((f_p[0]+f_s[0])*2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 0.0, 1.0); glMultiTexCoord2d(GL_TEXTURE1,  f_p[0]        , (f_p[1]+f_s[1]));             glVertex2d( f_p[0]        *2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
+               glEnd();\r
+               \r
+               // Cleanup\r
+\r
+               ogl_->disable(GL_SCISSOR_TEST); \r
+                                               \r
+               params.textures.clear();\r
+               ogl_->yield(); // Return resources to pool as early as possible.\r
+\r
+               if(blend_modes_)\r
+               {\r
+                       // http://www.opengl.org/registry/specs/NV/texture_barrier.txt\r
+                       // This allows us to use framebuffer (background) both as source and target while blending.\r
+                       glTextureBarrierNV(); \r
+               }\r
+       }\r
+};\r
+\r
+image_kernel::image_kernel(const safe_ptr<ogl_device>& ogl) : impl_(new implementation(ogl)){}\r
+void image_kernel::draw(draw_params&& params)\r
+{\r
+       impl_->draw(std::move(params));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/image_kernel.h b/core/mixer/image/image_kernel.h
new file mode 100644 (file)
index 0000000..ac378fc
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "blend_modes.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class device_buffer;\r
+class ogl_device;\r
+\r
+struct keyer\r
+{\r
+       enum type\r
+       {\r
+               linear = 0,\r
+               additive\r
+       };\r
+};\r
+\r
+struct draw_params\r
+{\r
+       pixel_format_desc                                               pix_desc;\r
+       std::vector<safe_ptr<device_buffer>>    textures;\r
+       frame_transform                                                 transform;\r
+       blend_mode::type                                                blend_mode;\r
+       keyer::type                                                             keyer;\r
+       std::shared_ptr<device_buffer>                  background;\r
+       std::shared_ptr<device_buffer>                  local_key;\r
+       std::shared_ptr<device_buffer>                  layer_key;\r
+\r
+       draw_params() \r
+               : blend_mode(blend_mode::normal)\r
+               , keyer(keyer::linear)\r
+       {\r
+       }\r
+};\r
+\r
+class image_kernel : boost::noncopyable\r
+{\r
+public:\r
+       image_kernel(const safe_ptr<ogl_device>& ogl);\r
+       void draw(draw_params&& params);\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/image_mixer.cpp b/core/mixer/image/image_mixer.cpp
new file mode 100644 (file)
index 0000000..339986f
--- /dev/null
@@ -0,0 +1,297 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "image_mixer.h"\r
+\r
+#include "image_kernel.h"\r
+#include "../write_frame.h"\r
+#include "../gpu/ogl_device.h"\r
+#include "../gpu/host_buffer.h"\r
+#include "../gpu/device_buffer.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/gl/gl_check.h>\r
+#include <common/utility/move_on_copy.h>\r
+\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/video_format.h>\r
+\r
+#include <gl/glew.h>\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm_ext/erase.hpp>\r
+\r
+#include <algorithm>\r
+#include <deque>\r
+\r
+using namespace boost::assign;\r
+\r
+namespace caspar { namespace core {\r
+       \r
+struct item\r
+{\r
+       pixel_format_desc                                               pix_desc;\r
+       std::vector<safe_ptr<device_buffer>>    textures;\r
+       frame_transform                                                 transform;\r
+};\r
+\r
+typedef std::pair<blend_mode::type, std::vector<item>> layer;\r
+\r
+class image_renderer\r
+{\r
+       safe_ptr<ogl_device>                    ogl_;\r
+       image_kernel                                    kernel_;        \r
+       std::shared_ptr<device_buffer>  transferring_buffer_;\r
+public:\r
+       image_renderer(const safe_ptr<ogl_device>& ogl)\r
+               : ogl_(ogl)\r
+               , kernel_(ogl_)\r
+       {\r
+       }\r
+       \r
+       boost::unique_future<safe_ptr<host_buffer>> operator()(std::vector<layer>&& layers, const video_format_desc& format_desc)\r
+       {               \r
+               auto layers2 = make_move_on_copy(std::move(layers));\r
+               return ogl_->begin_invoke([=]\r
+               {\r
+                       return do_render(std::move(layers2.value), format_desc);\r
+               });\r
+       }\r
+\r
+private:\r
+       safe_ptr<host_buffer> do_render(std::vector<layer>&& layers, const video_format_desc& format_desc)\r
+       {\r
+               auto draw_buffer = create_mixer_buffer(4, format_desc);\r
+\r
+               if(format_desc.field_mode != field_mode::progressive)\r
+               {\r
+                       auto upper = layers;\r
+                       auto lower = std::move(layers);\r
+\r
+                       BOOST_FOREACH(auto& layer, upper)\r
+                       {\r
+                               BOOST_FOREACH(auto& item, layer.second)\r
+                                       item.transform.field_mode = static_cast<field_mode::type>(item.transform.field_mode & field_mode::upper);\r
+                       }\r
+\r
+                       BOOST_FOREACH(auto& layer, lower)\r
+                       {\r
+                               BOOST_FOREACH(auto& item, layer.second)\r
+                                       item.transform.field_mode = static_cast<field_mode::type>(item.transform.field_mode & field_mode::lower);\r
+                       }\r
+\r
+                       draw(std::move(upper), draw_buffer, format_desc);\r
+                       draw(std::move(lower), draw_buffer, format_desc);\r
+               }\r
+               else\r
+               {\r
+                       draw(std::move(layers), draw_buffer, format_desc);\r
+               }\r
+\r
+               auto host_buffer = ogl_->create_host_buffer(format_desc.size, host_buffer::read_only);\r
+               ogl_->attach(*draw_buffer);\r
+               ogl_->read_buffer(*draw_buffer);\r
+               host_buffer->begin_read(draw_buffer->width(), draw_buffer->height(), format(draw_buffer->stride()));\r
+               \r
+               transferring_buffer_ = std::move(draw_buffer);\r
+\r
+               ogl_->flush(); // NOTE: This is important, otherwise fences will deadlock.\r
+                       \r
+               return host_buffer;\r
+       }\r
+\r
+       void draw(std::vector<layer>&&          layers, \r
+                         safe_ptr<device_buffer>&      draw_buffer, \r
+                         const video_format_desc& format_desc)\r
+       {\r
+               std::shared_ptr<device_buffer> layer_key_buffer;\r
+\r
+               BOOST_FOREACH(auto& layer, layers)\r
+                       draw_layer(std::move(layer), draw_buffer, layer_key_buffer, format_desc);\r
+       }\r
+\r
+       void draw_layer(layer&&                                                 layer, \r
+                                       safe_ptr<device_buffer>&                draw_buffer,\r
+                                       std::shared_ptr<device_buffer>& layer_key_buffer,\r
+                                       const video_format_desc&                format_desc)\r
+       {                               \r
+               boost::remove_erase_if(layer.second, [](const item& item){return item.transform.field_mode == field_mode::empty;});\r
+\r
+               if(layer.second.empty())\r
+                       return;\r
+\r
+               std::shared_ptr<device_buffer> local_key_buffer;\r
+               std::shared_ptr<device_buffer> local_mix_buffer;\r
+                               \r
+               if(layer.first != blend_mode::normal)\r
+               {\r
+                       auto layer_draw_buffer = create_mixer_buffer(4, format_desc);\r
+\r
+                       BOOST_FOREACH(auto& item, layer.second)\r
+                               draw_item(std::move(item), layer_draw_buffer, layer_key_buffer, local_key_buffer, local_mix_buffer, format_desc);       \r
+               \r
+                       draw_mixer_buffer(layer_draw_buffer, std::move(local_mix_buffer), blend_mode::normal);                                                  \r
+                       draw_mixer_buffer(draw_buffer, std::move(layer_draw_buffer), layer.first);\r
+               }\r
+               else // fast path\r
+               {\r
+                       BOOST_FOREACH(auto& item, layer.second)         \r
+                               draw_item(std::move(item), draw_buffer, layer_key_buffer, local_key_buffer, local_mix_buffer, format_desc);             \r
+                                       \r
+                       draw_mixer_buffer(draw_buffer, std::move(local_mix_buffer), blend_mode::normal);\r
+               }                                       \r
+\r
+               layer_key_buffer = std::move(local_key_buffer);\r
+       }\r
+\r
+       void draw_item(item&&                                                   item, \r
+                                  safe_ptr<device_buffer>&                     draw_buffer, \r
+                                  std::shared_ptr<device_buffer>&      layer_key_buffer, \r
+                                  std::shared_ptr<device_buffer>&      local_key_buffer, \r
+                                  std::shared_ptr<device_buffer>&      local_mix_buffer,\r
+                                  const video_format_desc&                     format_desc)\r
+       {                       \r
+               draw_params draw_params;\r
+               draw_params.pix_desc                            = std::move(item.pix_desc);\r
+               draw_params.textures                            = std::move(item.textures);\r
+               draw_params.transform                           = std::move(item.transform);\r
+\r
+               if(item.transform.is_key)\r
+               {\r
+                       local_key_buffer = local_key_buffer ? local_key_buffer : create_mixer_buffer(1, format_desc);\r
+\r
+                       draw_params.background                  = local_key_buffer;\r
+                       draw_params.local_key                   = nullptr;\r
+                       draw_params.layer_key                   = nullptr;\r
+\r
+                       kernel_.draw(std::move(draw_params));\r
+               }\r
+               else if(item.transform.is_mix)\r
+               {\r
+                       local_mix_buffer = local_mix_buffer ? local_mix_buffer : create_mixer_buffer(4, format_desc);\r
+\r
+                       draw_params.background                  = local_mix_buffer;\r
+                       draw_params.local_key                   = std::move(local_key_buffer);\r
+                       draw_params.layer_key                   = layer_key_buffer;\r
+\r
+                       draw_params.keyer                               = keyer::additive;\r
+\r
+                       kernel_.draw(std::move(draw_params));\r
+               }\r
+               else\r
+               {\r
+                       draw_mixer_buffer(draw_buffer, std::move(local_mix_buffer), blend_mode::normal);\r
+                       \r
+                       draw_params.background                  = draw_buffer;\r
+                       draw_params.local_key                   = std::move(local_key_buffer);\r
+                       draw_params.layer_key                   = layer_key_buffer;\r
+\r
+                       kernel_.draw(std::move(draw_params));\r
+               }       \r
+       }\r
+\r
+       void draw_mixer_buffer(safe_ptr<device_buffer>&                 draw_buffer, \r
+                                                  std::shared_ptr<device_buffer>&& source_buffer, \r
+                                                  blend_mode::type                                     blend_mode = blend_mode::normal)\r
+       {\r
+               if(!source_buffer)\r
+                       return;\r
+\r
+               draw_params draw_params;\r
+               draw_params.pix_desc.pix_fmt    = pixel_format::bgra;\r
+               draw_params.pix_desc.planes             = list_of(pixel_format_desc::plane(source_buffer->width(), source_buffer->height(), 4));\r
+               draw_params.textures                    = list_of(source_buffer);\r
+               draw_params.transform                   = frame_transform();\r
+               draw_params.blend_mode                  = blend_mode;\r
+               draw_params.background                  = draw_buffer;\r
+\r
+               kernel_.draw(std::move(draw_params));\r
+       }\r
+                       \r
+       safe_ptr<device_buffer> create_mixer_buffer(size_t stride, const video_format_desc& format_desc)\r
+       {\r
+               auto buffer = ogl_->create_device_buffer(format_desc.width, format_desc.height, stride);\r
+               ogl_->clear(*buffer);\r
+               return buffer;\r
+       }\r
+};\r
+               \r
+struct image_mixer::implementation : boost::noncopyable\r
+{      \r
+       safe_ptr<ogl_device>                    ogl_;\r
+       image_renderer                                  renderer_;\r
+       std::vector<frame_transform>    transform_stack_;\r
+       std::vector<layer>                              layers_; // layer/stream/items\r
+public:\r
+       implementation(const safe_ptr<ogl_device>& ogl) \r
+               : ogl_(ogl)\r
+               , renderer_(ogl)\r
+               , transform_stack_(1)   \r
+       {\r
+       }\r
+\r
+       void begin_layer(blend_mode::type blend_mode)\r
+       {\r
+               layers_.push_back(std::make_pair(blend_mode, std::vector<item>()));\r
+       }\r
+               \r
+       void begin(basic_frame& frame)\r
+       {\r
+               transform_stack_.push_back(transform_stack_.back()*frame.get_frame_transform());\r
+       }\r
+               \r
+       void visit(write_frame& frame)\r
+       {                       \r
+               item item;\r
+               item.pix_desc   = frame.get_pixel_format_desc();\r
+               item.textures   = frame.get_textures();\r
+               item.transform  = transform_stack_.back();\r
+\r
+               layers_.back().second.push_back(item);\r
+       }\r
+\r
+       void end()\r
+       {\r
+               transform_stack_.pop_back();\r
+       }\r
+\r
+       void end_layer()\r
+       {               \r
+       }\r
+       \r
+       boost::unique_future<safe_ptr<host_buffer>> render(const video_format_desc& format_desc)\r
+       {\r
+               return renderer_(std::move(layers_), format_desc);\r
+       }\r
+};\r
+\r
+image_mixer::image_mixer(const safe_ptr<ogl_device>& ogl) : impl_(new implementation(ogl)){}\r
+void image_mixer::begin(basic_frame& frame){impl_->begin(frame);}\r
+void image_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
+void image_mixer::end(){impl_->end();}\r
+boost::unique_future<safe_ptr<host_buffer>> image_mixer::operator()(const video_format_desc& format_desc){return impl_->render(format_desc);}\r
+void image_mixer::begin_layer(blend_mode::type blend_mode){impl_->begin_layer(blend_mode);}\r
+void image_mixer::end_layer(){impl_->end_layer();}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/image_mixer.h b/core/mixer/image/image_mixer.h
new file mode 100644 (file)
index 0000000..664d7c2
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "blend_modes.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/producer/frame/frame_visitor.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <boost/thread/future.hpp>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class write_frame;\r
+class host_buffer;\r
+class ogl_device;\r
+struct video_format_desc;\r
+struct pixel_format_desc;\r
+\r
+class image_mixer : public core::frame_visitor, boost::noncopyable\r
+{\r
+public:\r
+       image_mixer(const safe_ptr<ogl_device>& ogl);\r
+       \r
+       virtual void begin(core::basic_frame& frame);\r
+       virtual void visit(core::write_frame& frame);\r
+       virtual void end();\r
+\r
+       void begin_layer(blend_mode::type blend_mode);\r
+       void end_layer();\r
+               \r
+       boost::unique_future<safe_ptr<host_buffer>> operator()(const video_format_desc& format_desc);\r
+               \r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/image/shader/blending_glsl.h b/core/mixer/image/shader/blending_glsl.h
new file mode 100644 (file)
index 0000000..aab2ae4
--- /dev/null
@@ -0,0 +1,270 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+static std::string get_adjustement_glsl()\r
+{\r
+       return                                                                                                                                                                                                                                                                                                                                                                                                                                          \r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Contrast, saturation, brightness                                                                                                                                                                                                                                                                                                                                                              "\r
+               "\n     ** Code of this function is from TGM's shader pack                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057                                                                                                                                                                                                                                                                                                 "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con)                                                                                                                                                                                                                                                                     "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             const float AvgLumR = 0.5;                                                                                                                                                                                                                                                                                                                                                                         "\r
+               "\n             const float AvgLumG = 0.5;                                                                                                                                                                                                                                                                                                                                                                         "\r
+               "\n             const float AvgLumB = 0.5;                                                                                                                                                                                                                                                                                                                                                                         "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);                                                                                                                                                                                                                                                                                                                           "\r
+               "\n             vec3 brtColor = color * brt;                                                                                                                                                                                                                                                                                                                                                               "\r
+               "\n             vec3 intensity = vec3(dot(brtColor, LumCoeff));                                                                                                                                                                                                                                                                                                                            "\r
+               "\n             vec3 satColor = mix(intensity, brtColor, sat);                                                                                                                                                                                                                                                                                                                             "\r
+               "\n             vec3 conColor = mix(AvgLumin, satColor, con);                                                                                                                                                                                                                                                                                                                              "\r
+               "\n             return conColor;                                                                                                                                                                                                                                                                                                                                                                                           "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Gamma correction                                                                                                                                                                                                                                                                                                                                                                                                     "\r
+               "\n     ** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/                                                                                                                                                                                                                                                                   "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n#define GammaCorrection(color, gamma)                                                                pow(color, vec3(1.0 / gamma))                           \n                                                                                                                                                                                                      "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Levels control (input (+gamma), output)                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/                                                                                                                                                                                                                                                                                       "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n#define LevelsControlInputRange(color, minInput, maxInput)                           min(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0))              \n                                                                                 "\r
+               "\n#define LevelsControlInput(color, minInput, gamma, maxInput)                         GammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma)                                      \n                                                                                              "       \r
+               "\n#define LevelsControlOutputRange(color, minOutput, maxOutput)                        mix(vec3(minOutput), vec3(maxOutput), color)                                                                                                                    \n                                                                 "\r
+               "\n#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput)        LevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput)    \n                                                      "\r
+               ;\r
+}\r
+\r
+static std::string get_blend_glsl()\r
+{\r
+       static std::string glsl = \r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Photoshop & misc math                                                                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n     ** Blending modes, RGB/HSL/Contrast/Desaturate, levels control                                                                                                                                                                                                                                                                                                     "\r
+               "\n     **                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Romain Dura | Romz                                                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n     ** Blog: http://blog.mouaif.org                                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n     ** Post: http://blog.mouaif.org/?p=94                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Desaturation                                                                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec4 Desaturate(vec3 color, float Desaturation)                                                                                                                                                                                                                                                                                                                            "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 grayXfer = vec3(0.3, 0.59, 0.11);                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n             vec3 gray = vec3(dot(grayXfer, color));                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n             return vec4(mix(color, gray, Desaturation), 1.0);                                                                                                                                                                                                                                                                                                                          "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Hue, saturation, luminance                                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 RGBToHSL(vec3 color)                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 hsl;                                                                                                                                                                                                                                                          "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             float fmin = min(min(color.r, color.g), color.b);                                                                                                                                                                                                                                                                  "\r
+               "\n             float fmax = max(max(color.r, color.g), color.b);                                                                                                                                                                                                                                                                  "\r
+               "\n             float delta = fmax - fmin;                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             hsl.z = (fmax + fmin) / 2.0;                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             if (delta == 0.0)                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             {                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                     hsl.x = 0.0;                                                                                                                                                                                                                                                                                                                                                               "\r
+               "\n                     hsl.y = 0.0;                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n             }                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n             else                                                                                                                                                                                                                                                                                                                       "\r
+               "\n             {                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                     if (hsl.z < 0.5)                                                                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n                             hsl.y = delta / (fmax + fmin);                                                                                                                                                                                                                                                                                             "\r
+               "\n                     else                                                                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                             hsl.y = delta / (2.0 - fmax - fmin);                                                                                                                                                                                                                                                                                               "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;                                                                                                                                                                                                                                                                                 "\r
+               "\n                     float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;                                                                                                                                                                                                                                                                                 "\r
+               "\n                     float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     if (color.r == fmax )                                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n                             hsl.x = deltaB - deltaG;                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n                     else if (color.g == fmax)                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                             hsl.x = (1.0 / 3.0) + deltaR - deltaB;                                                                                                                                                                                                                                                                                                     "\r
+               "\n                     else if (color.b == fmax)                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                             hsl.x = (2.0 / 3.0) + deltaG - deltaR;                                                                                                                                                                                                                                                                                                     "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     if (hsl.x < 0.0)                                                                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n                             hsl.x += 1.0;                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n                     else if (hsl.x > 1.0)                                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n                             hsl.x -= 1.0;                                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n             }                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             return hsl;                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     float HueToRGB(float f1, float f2, float hue)                                                                                                                                                                                                                                                                                                                                      "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             if (hue < 0.0)                                                                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n                     hue += 1.0;                                                                                                                                                                                                                                                                                                                                                                                                "\r
+               "\n             else if (hue > 1.0)                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     hue -= 1.0;                                                                                                                                                                                                                                                                                                                                                                                                "\r
+               "\n             float res;                                                                                                                                                                                                                                                                                                                                                                                                         "\r
+               "\n             if ((6.0 * hue) < 1.0)                                                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n                     res = f1 + (f2 - f1) * 6.0 * hue;                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             else if ((2.0 * hue) < 1.0)                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     res = f2;                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             else if ((3.0 * hue) < 2.0)                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             else                                                                                                                                                                                                                                                                                                                                                                                                               "\r
+               "\n                     res = f1;                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             return res;                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 HSLToRGB(vec3 hsl)                                                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 rgb;                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             if (hsl.y == 0.0)                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                     rgb = vec3(hsl.z);                                                                                                                                                                                                                                                                                                                                         "\r
+               "\n             else                                                                                                                                                                                                                                                                                                                                                                                                               "\r
+               "\n             {                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                     float f2;                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     if (hsl.z < 0.5)                                                                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n                             f2 = hsl.z * (1.0 + hsl.y);                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     else                                                                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                             f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);                                                                                                                                                                                                                                                                                                                            "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     float f1 = 2.0 * hsl.z - f2;                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                     rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));                                                                                                                                                                                                                                                                                                                       "\r
+               "\n                     rgb.g = HueToRGB(f1, f2, hsl.x);                                                                                                                                                                                                                                                                                                                                                   "\r
+               "\n                     rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));                                                                                                                                                                                                                                                                                                                                "\r
+               "\n             }                                                                                                                                                                                                                                                                                                                                                                                                                          "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n             return rgb;                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                                "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Float blending modes                                                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n     ** Adapted from here: http://www.nathanm.com/photoshop-blending-math/                                                                                                                                                                                                                                                                                      "\r
+               "\n     ** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results                                                                                            "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                             \n                                         "\r
+               "\n#define BlendLinearDodgef                                    BlendAddf                                                                                                                                                                                                                                                                               \n                                                 "\r
+               "\n#define BlendLinearBurnf                                     BlendSubstractf                                                                                                                                                                                                                                                                 \n                                                 "\r
+               "\n#define BlendAddf(base, blend)                               min(base + blend, 1.0)                                                                                                                                                                                                                                                  \n                                         "\r
+               "\n#define BlendSubstractf(base, blend)                 max(base + blend - 1.0, 0.0)                                                                                                                                                                                                                                    \n                                                 "\r
+               "\n#define BlendLightenf(base, blend)           max(blend, base)                                                                                                                                                                                                                                                                        \n                                 "\r
+               "\n#define BlendDarkenf(base, blend)                    min(blend, base)                                                                                                                                                                                                                                                                \n                                                 "\r
+               "\n#define BlendLinearLightf(base, blend)       (blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5))))                                                                                          \n                                 "\r
+               "\n#define BlendScreenf(base, blend)                    (1.0 - ((1.0 - base) * (1.0 - blend)))                                                                                                                                                                                                                  \n                                                 "\r
+               "\n#define BlendOverlayf(base, blend)           (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))                                                                                                                                        \n                                         "\r
+               "\n#define BlendSoftLightf(base, blend)                 ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))    \n                                                 "\r
+               "\n#define BlendColorDodgef(base, blend)                ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))                                                                                                                                                                               \n                                                 "\r
+               "\n#define BlendColorBurnf(base, blend)                 ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))                                                                                                                                                             \n                                                 "\r
+               "\n#define BlendVividLightf(base, blend)                ((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5))))                                                                                  \n                                                 "\r
+               "\n#define BlendPinLightf(base, blend)          ((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5))))                                                                                                         \n                                         "\r
+               "\n#define BlendHardMixf(base, blend)           ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0)                                                                                                                                                                                                     \n                                         "\r
+               "\n#define BlendReflectf(base, blend)           ((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0))                                                                                                                                                                        \n                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     /*                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n     ** Vector3 blending modes                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n     */                                                                                                                                                                                                                                                                                                                                                                                                                                 "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n#define Blend(base, blend, funcf)                    vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))                            \n                                                                                                                                                         "\r
+               "\n                                                                                                                                                                                                                                                                                     \n                                                                                                                                                 "\r
+               "\n#define BlendNormal(base, blend)                     (blend)                                                                                                                                                                         \n                                                                                                                                                         "\r
+               "\n#define BlendLighten                                         BlendLightenf                                                                                                                                                                   \n                                                                                                                                                         "\r
+               "\n#define BlendDarken                                          BlendDarkenf                                                                                                                                                                    \n                                                                                                                                                         "\r
+               "\n#define BlendMultiply(base, blend)           (base * blend)                                                                                                                                                                  \n                                                                                                                                         "\r
+               "\n#define BlendAverage(base, blend)                    ((base + blend) / 2.0)                                                                                                                                          \n                                                                                                                                                         "\r
+               "\n#define BlendAdd(base, blend)                                min(base + blend, vec3(1.0))                                                                                                                            \n                                                                                                                                                                 "\r
+               "\n#define BlendSubstract(base, blend)          max(base + blend - vec3(1.0), vec3(0.0))                                                                                                                \n                                                                                                                                                 "\r
+               "\n#define BlendDifference(base, blend)                 abs(base - blend)                                                                                                                                                       \n                                                                                                                                                         "\r
+               "\n#define BlendNegation(base, blend)           (vec3(1.0) - abs(vec3(1.0) - base - blend))                                                                                                             \n                                                                                                                                                 "\r
+               "\n#define BlendExclusion(base, blend)          (base + blend - 2.0 * base * blend)                                                                                                                             \n                                                                                                                                                 "\r
+               "\n#define BlendScreen(base, blend)                     Blend(base, blend, BlendScreenf)                                                                                                                        \n                                                                                                                                                         "\r
+               "\n#define BlendOverlay(base, blend)                    Blend(base, blend, BlendOverlayf)                                                                                                                       \n                                                                                                                                                         "\r
+               "\n#define BlendSoftLight(base, blend)          Blend(base, blend, BlendSoftLightf)                                                                                                                             \n                                                                                                                                                 "\r
+               "\n#define BlendHardLight(base, blend)          BlendOverlay(blend, base)                                                                                                                                               \n                                                                                                                                                 "\r
+               "\n#define BlendColorDodge(base, blend)                 Blend(base, blend, BlendColorDodgef)                                                                                                            \n                                                                                                                                                         "\r
+               "\n#define BlendColorBurn(base, blend)          Blend(base, blend, BlendColorBurnf)                                                                                                                             \n                                                                                                                                                 "\r
+               "\n#define BlendLinearDodge                                     BlendAdd                                                                                                                                                                                \n                                                                                                                                                         "\r
+               "\n#define BlendLinearBurn                                      BlendSubstract                                                                                                                                                                  \n                                                                                                                                                         "\r
+               "\n#define BlendLinearLight(base, blend)                Blend(base, blend, BlendLinearLightf)                                                                                                           \n                                                                                                                                                         "\r
+               "\n#define BlendVividLight(base, blend)                 Blend(base, blend, BlendVividLightf)                                                                                                            \n                                                                                                                                                         "\r
+               "\n#define BlendPinLight(base, blend)           Blend(base, blend, BlendPinLightf)                                                                                                                              \n                                                                                                                                         "\r
+               "\n#define BlendHardMix(base, blend)                    Blend(base, blend, BlendHardMixf)                                                                                                                       \n                                                                                                                                                         "\r
+               "\n#define BlendReflect(base, blend)                    Blend(base, blend, BlendReflectf)                                                                                                                       \n                                                                                                                                                         "\r
+               "\n#define BlendGlow(base, blend)                       BlendReflect(blend, base)                                                                                                                                               \n                                                                                                                                                 "\r
+               "\n#define BlendPhoenix(base, blend)                    (min(base, blend) - max(base, blend) + vec3(1.0))                                                                                       \n                                                                                                                                                         "\r
+               "\n#define BlendOpacity(base, blend, F, O)      (F(base, blend) * O + blend * (1.0 - O))                                                                                                                \n                                                                                                                                                         "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 BlendHue(vec3 base, vec3 blend)                                                                                                                                                                                                                                                                                                                                                       "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 baseHSL = RGBToHSL(base);                                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n             return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b));                                                                                                                                                                                                                                                                                            "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 BlendSaturation(vec3 base, vec3 blend)                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 baseHSL = RGBToHSL(base);                                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n             return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b));                                                                                                                                                                                                                                                                                            "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 BlendColor(vec3 base, vec3 blend)                                                                                                                                                                                                                                                                                                                                                     "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 blendHSL = RGBToHSL(blend);                                                                                                                                                                                                                                                                                                                                                           "\r
+               "\n             return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));                                                                                                                                                                                                                                                                                           "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     vec3 BlendLuminosity(vec3 base, vec3 blend)                                                                                                                                                                                                                                                                                                                                        "\r
+               "\n     {                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n             vec3 baseHSL = RGBToHSL(base);                                                                                                                                                                                                                                                                                                                                                             "\r
+               "\n             return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b));                                                                                                                                                                                                                                                                                            "\r
+               "\n     }                                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
+               "\n                                                                                                                                                                                                                                                                                                                                                                                                        "\r
+               ;\r
+                                                                                                                                                                                                                                                                                                                                                                                                                                                  \r
+               return glsl;\r
+}
\ No newline at end of file
diff --git a/core/mixer/image/shader/image_shader.cpp b/core/mixer/image/shader/image_shader.cpp
new file mode 100644 (file)
index 0000000..28550b3
--- /dev/null
@@ -0,0 +1,288 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../../StdAfx.h"\r
+\r
+#include "image_shader.h"\r
+\r
+#include "../../gpu/shader.h"\r
+#include "../../gpu/ogl_device.h"\r
+\r
+#include "blending_glsl.h"\r
+\r
+#include <common/gl/gl_check.h>\r
+#include <common/env.h>\r
+\r
+#include <tbb/mutex.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+std::shared_ptr<shader> g_shader;\r
+tbb::mutex                             g_shader_mutex;\r
+bool                                   g_blend_modes = false;\r
+\r
+std::string get_blend_color_func()\r
+{\r
+       return \r
+                       \r
+       get_adjustement_glsl()\r
+               \r
+       +\r
+\r
+       get_blend_glsl()\r
+               \r
+       +\r
+                       \r
+       "vec3 get_blend_color(vec3 back, vec3 fore)                                                                                     \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       switch(blend_mode)                                                                                                                              \n"\r
+       "       {                                                                                                                                                               \n"\r
+       "       case  0: return BlendNormal(back, fore);                                                                                \n"\r
+       "       case  1: return BlendLighten(back, fore);                                                                               \n"\r
+       "       case  2: return BlendDarken(back, fore);                                                                                \n"\r
+       "       case  3: return BlendMultiply(back, fore);                                                                              \n"\r
+       "       case  4: return BlendAverage(back, fore);                                                                               \n"\r
+       "       case  5: return BlendAdd(back, fore);                                                                                   \n"\r
+       "       case  6: return BlendSubstract(back, fore);                                                                             \n"\r
+       "       case  7: return BlendDifference(back, fore);                                                                    \n"\r
+       "       case  8: return BlendNegation(back, fore);                                                                              \n"\r
+       "       case  9: return BlendExclusion(back, fore);                                                                             \n"\r
+       "       case 10: return BlendScreen(back, fore);                                                                                \n"\r
+       "       case 11: return BlendOverlay(back, fore);                                                                               \n"\r
+       //"     case 12: return BlendSoftLight(back, fore);                                                                             \n"\r
+       "       case 13: return BlendHardLight(back, fore);                                                                             \n"\r
+       "       case 14: return BlendColorDodge(back, fore);                                                                    \n"\r
+       "       case 15: return BlendColorBurn(back, fore);                                                                             \n"\r
+       "       case 16: return BlendLinearDodge(back, fore);                                                                   \n"\r
+       "       case 17: return BlendLinearBurn(back, fore);                                                                    \n"\r
+       "       case 18: return BlendLinearLight(back, fore);                                                                   \n"\r
+       "       case 19: return BlendVividLight(back, fore);                                                                    \n"\r
+       "       case 20: return BlendPinLight(back, fore);                                                                              \n"\r
+       "       case 21: return BlendHardMix(back, fore);                                                                               \n"\r
+       "       case 22: return BlendReflect(back, fore);                                                                               \n"\r
+       "       case 23: return BlendGlow(back, fore);                                                                                  \n"\r
+       "       case 24: return BlendPhoenix(back, fore);                                                                               \n"\r
+       "       case 25: return BlendHue(back, fore);                                                                                   \n"\r
+       "       case 26: return BlendSaturation(back, fore);                                                                    \n"\r
+       "       case 27: return BlendColor(back, fore);                                                                                 \n"\r
+       "       case 28: return BlendLuminosity(back, fore);                                                                    \n"\r
+       "       }                                                                                                                                                               \n"\r
+       "       return BlendNormal(back, fore);                                                                                                 \n"\r
+       "}                                                                                                                                                                      \n"\r
+       "                                                                                                                                                                       \n"                                                                                                                                                       \r
+       "vec4 blend(vec4 fore)                                                                                                                          \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "   vec4 back = texture2D(background, gl_TexCoord[1].st).bgra;                                          \n"\r
+       "   if(blend_mode != 0)                                                                                                                         \n"\r
+       "               fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a;\n"\r
+       "       switch(keyer)                                                                                                                                   \n"     \r
+       "       {                                                                                                                                                               \n"     \r
+       "               case 1:  return fore + back; // additive                                                                        \n"\r
+       "               default: return fore + (1.0-fore.a)*back; // linear                                                     \n"\r
+       "       }                                                                                                                                                               \n"\r
+       "}                                                                                                                                                                      \n";                    \r
+}\r
+               \r
+std::string get_simple_blend_color_func()\r
+{\r
+       return  \r
+               \r
+       get_adjustement_glsl()\r
+                       \r
+       +\r
+\r
+       "vec4 blend(vec4 fore)                                                                                                                          \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       return fore;                                                                                                                                    \n"\r
+       "}                                                                                                                                                                      \n";\r
+}\r
+\r
+std::string get_vertex()\r
+{\r
+       return \r
+\r
+       "void main()                                                                                                                                            \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                                             \n"\r
+       "       gl_TexCoord[1] = gl_MultiTexCoord1;                                                                                             \n"\r
+       "       gl_Position    = ftransform();                                                                                                  \n"\r
+       "}                                                                                                                                                                      \n";\r
+}\r
+\r
+std::string get_fragment(bool blend_modes)\r
+{\r
+       return\r
+\r
+       "#version 130                                                                                                                                           \n"\r
+       "uniform sampler2D      background;                                                                                                             \n"\r
+       "uniform sampler2D      plane[4];                                                                                                               \n"\r
+       "uniform sampler2D      local_key;                                                                                                              \n"\r
+       "uniform sampler2D      layer_key;                                                                                                              \n"\r
+       "                                                                                                                                                                       \n"\r
+       "uniform bool           is_hd;                                                                                                                  \n"\r
+       "uniform bool           has_local_key;                                                                                                  \n"\r
+       "uniform bool           has_layer_key;                                                                                                  \n"\r
+       "uniform int            blend_mode;                                                                                                             \n"\r
+       "uniform int            keyer;                                                                                                                  \n"\r
+       "uniform int            pixel_format;                                                                                                   \n"\r
+       "                                                                                                                                                                       \n"\r
+       "uniform float          opacity;                                                                                                                \n"\r
+       "uniform bool           levels;                                                                                                                 \n"\r
+       "uniform float          min_input;                                                                                                              \n"\r
+       "uniform float          max_input;                                                                                                              \n"\r
+       "uniform float          gamma;                                                                                                                  \n"\r
+       "uniform float          min_output;                                                                                                             \n"\r
+       "uniform float          max_output;                                                                                                             \n"\r
+       "                                                                                                                                                                       \n"\r
+       "uniform bool           csb;                                                                                                                    \n"\r
+       "uniform float          brt;                                                                                                                    \n"\r
+       "uniform float          sat;                                                                                                                    \n"\r
+       "uniform float          con;                                                                                                                    \n"\r
+       "                                                                                                                                                                       \n"     \r
+\r
+       +\r
+               \r
+       (blend_modes ? get_blend_color_func() : get_simple_blend_color_func())\r
+\r
+       +\r
+       \r
+       "                                                                                                                                                                       \n"\r
+       "vec4 ycbcra_to_rgba_sd(float Y, float Cb, float Cr, float A)                                           \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "   vec4 rgba;                                                                                                                                          \n"\r
+       "   rgba.b = (1.164*(Y*255 - 16) + 1.596*(Cr*255 - 128))/255;                                           \n"\r
+       "   rgba.g = (1.164*(Y*255 - 16) - 0.813*(Cr*255 - 128) - 0.391*(Cb*255 - 128))/255;\n"\r
+       "   rgba.r = (1.164*(Y*255 - 16) + 2.018*(Cb*255 - 128))/255;                                           \n"\r
+       "   rgba.a = A;                                                                                                                                         \n"\r
+       "       return rgba;                                                                                                                                    \n"     \r
+       "}                                                                                                                                                                      \n"                     \r
+       "                                                                                                                                                                       \n"\r
+       "vec4 ycbcra_to_rgba_hd(float Y, float Cb, float Cr, float A)                                           \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "   vec4 rgba;                                                                                                                                          \n"\r
+       "   rgba.b = (1.164*(Y*255 - 16) + 1.793*(Cr*255 - 128))/255;                                           \n"\r
+       "   rgba.g = (1.164*(Y*255 - 16) - 0.534*(Cr*255 - 128) - 0.213*(Cb*255 - 128))/255;\n"\r
+       "   rgba.r = (1.164*(Y*255 - 16) + 2.115*(Cb*255 - 128))/255;                                           \n"\r
+       "   rgba.a = A;                                                                                                                                         \n"\r
+       "       return rgba;                                                                                                                                    \n"\r
+       "}                                                                                                                                                                      \n"                     \r
+       "                                                                                                                                                                       \n"             \r
+       "vec4 ycbcra_to_rgba(float y, float cb, float cr, float a)                                                      \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       if(is_hd)                                                                                                                                               \n"\r
+       "               return ycbcra_to_rgba_hd(y, cb, cr, a);                                                                         \n"\r
+       "       else                                                                                                                                                    \n"\r
+       "               return ycbcra_to_rgba_sd(y, cb, cr, a);                                                                         \n"\r
+       "}                                                                                                                                                                      \n"\r
+       "                                                                                                                                                                       \n"\r
+       "vec4 get_rgba_color()                                                                                                                          \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       switch(pixel_format)                                                                                                                    \n"\r
+       "       {                                                                                                                                                               \n"\r
+       "       case 0:         //gray                                                                                                                          \n"\r
+       "               return vec4(texture2D(plane[0], gl_TexCoord[0].st).rrr, 1.0);                           \n"\r
+       "       case 1:         //bgra,                                                                                                                         \n"\r
+       "               return texture2D(plane[0], gl_TexCoord[0].st).bgra;                                                     \n"\r
+       "       case 2:         //rgba,                                                                                                                         \n"\r
+       "               return texture2D(plane[0], gl_TexCoord[0].st).rgba;                                                     \n"\r
+       "       case 3:         //argb,                                                                                                                         \n"\r
+       "               return texture2D(plane[0], gl_TexCoord[0].st).argb;                                                     \n"\r
+       "       case 4:         //abgr,                                                                                                                         \n"\r
+       "               return texture2D(plane[0], gl_TexCoord[0].st).gbar;                                                     \n"\r
+       "       case 5:         //ycbcr,                                                                                                                        \n"\r
+       "               {                                                                                                                                                       \n"\r
+       "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       return ycbcra_to_rgba(y, cb, cr, 1.0);                                                                  \n"\r
+       "               }                                                                                                                                                       \n"\r
+       "       case 6:         //ycbcra                                                                                                                        \n"\r
+       "               {                                                                                                                                                       \n"\r
+       "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       float a  = texture2D(plane[3], gl_TexCoord[0].st).r;                                    \n"\r
+       "                       return ycbcra_to_rgba(y, cb, cr, a);                                                                    \n"\r
+       "               }                                                                                                                                                       \n"\r
+       "       case 7:         //luma                                                                                                                          \n"\r
+       "               {                                                                                                                                                       \n"\r
+       "                       vec3 y3 = texture2D(plane[0], gl_TexCoord[0].st).rrr;                                   \n"\r
+       "                       return vec4((y3-0.065)/0.859, 1.0);                                                                             \n"\r
+       "               }                                                                                                                                                       \n"\r
+       "       }                                                                                                                                                               \n"\r
+       "       return vec4(0.0, 0.0, 0.0, 0.0);                                                                                                \n"\r
+       "}                                                                                                                                                                      \n"\r
+       "                                                                                                                                                                       \n"\r
+       "void main()                                                                                                                                            \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       vec4 color = get_rgba_color();                                                                                                  \n"\r
+       "   if(levels)                                                                                                                                          \n"\r
+       "               color.rgb = LevelsControl(color.rgb, min_input, max_input, gamma, min_output, max_output); \n"\r
+       "       if(csb)                                                                                                                                                 \n"\r
+       "               color.rgb = ContrastSaturationBrightness(color.rgb, brt, sat, con);                     \n"\r
+       "       if(has_local_key)                                                                                                                               \n"\r
+       "               color *= texture2D(local_key, gl_TexCoord[1].st).r;                                                     \n"\r
+       "       if(has_layer_key)                                                                                                                               \n"\r
+       "               color *= texture2D(layer_key, gl_TexCoord[1].st).r;                                                     \n"\r
+       "       color *= opacity;                                                                                                                               \n"\r
+       "       color = blend(color);                                                                                                                   \n"\r
+       "       gl_FragColor = color.bgra;                                                                                                              \n"\r
+       "}                                                                                                                                                                      \n";\r
+}\r
+\r
+safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes)\r
+{\r
+       tbb::mutex::scoped_lock lock(g_shader_mutex);\r
+\r
+       if(g_shader)\r
+       {\r
+               blend_modes = g_blend_modes;\r
+               return make_safe_ptr(g_shader);\r
+       }\r
+               \r
+       try\r
+       {                               \r
+               g_blend_modes  = glTextureBarrierNV ? env::properties().get(L"configuration.blend-modes", false) : false;\r
+               g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";\r
+                               \r
+               g_blend_modes = false;\r
+               g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
+       }\r
+                                               \r
+       ogl.enable(GL_TEXTURE_2D);\r
+\r
+       if(!g_blend_modes)\r
+       {\r
+               ogl.enable(GL_BLEND);\r
+               glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);\r
+               CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";\r
+       }\r
+\r
+       blend_modes = g_blend_modes;\r
+       return make_safe_ptr(g_shader);\r
+}\r
+\r
+}}\r
diff --git a/core/mixer/image/shader/image_shader.h b/core/mixer/image/shader/image_shader.h
new file mode 100644 (file)
index 0000000..11dc499
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class shader;\r
+class ogl_device;\r
+\r
+struct texture_id\r
+{\r
+       enum type\r
+       {\r
+               plane0 = 0,\r
+               plane1,\r
+               plane2,\r
+               plane3,\r
+               local_key,\r
+               layer_key,\r
+               background,\r
+       };\r
+};\r
+\r
+safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes);\r
+\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp
new file mode 100644 (file)
index 0000000..34bad45
--- /dev/null
@@ -0,0 +1,195 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "mixer.h"\r
+\r
+#include "read_frame.h"\r
+#include "write_frame.h"\r
+\r
+#include "audio/audio_mixer.h"\r
+#include "image/image_mixer.h"\r
+\r
+#include <common/env.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/gl/gl_check.h>\r
+#include <common/utility/tweener.h>\r
+\r
+#include <core/mixer/read_frame.h>\r
+#include <core/mixer/write_frame.h>\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/spin_mutex.h>\r
+\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+struct mixer::implementation : boost::noncopyable\r
+{              \r
+       safe_ptr<diagnostics::graph>    graph_;\r
+       boost::timer                                    mix_timer_;\r
+\r
+       safe_ptr<mixer::target_t>               target_;\r
+       mutable tbb::spin_mutex                 format_desc_mutex_;\r
+       video_format_desc                               format_desc_;\r
+       safe_ptr<ogl_device>                    ogl_;\r
+       \r
+       audio_mixer     audio_mixer_;\r
+       image_mixer image_mixer_;\r
+       \r
+       std::unordered_map<int, blend_mode::type> blend_modes_;\r
+                       \r
+       executor executor_;\r
+\r
+public:\r
+       implementation(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<mixer::target_t>& target, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
+               : graph_(graph)\r
+               , target_(target)\r
+               , format_desc_(format_desc)\r
+               , ogl_(ogl)\r
+               , image_mixer_(ogl)\r
+               , audio_mixer_(graph_)\r
+               , executor_(L"mixer")\r
+       {                       \r
+               graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
+       }\r
+       \r
+       void send(const std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>& packet)\r
+       {                       \r
+               executor_.begin_invoke([=]\r
+               {               \r
+                       try\r
+                       {\r
+                               mix_timer_.restart();\r
+\r
+                               auto frames = packet.first;\r
+                               \r
+                               BOOST_FOREACH(auto& frame, frames)\r
+                               {\r
+                                       auto blend_it = blend_modes_.find(frame.first);\r
+                                       image_mixer_.begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal);\r
+                                                                                                       \r
+                                       frame.second->accept(audio_mixer_);                                     \r
+                                       frame.second->accept(image_mixer_);\r
+\r
+                                       image_mixer_.end_layer();\r
+                               }\r
+\r
+                               auto image = image_mixer_(format_desc_);\r
+                               auto audio = audio_mixer_(format_desc_);\r
+                               image.wait();\r
+\r
+                               graph_->set_value("mix-time", mix_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+                               target_->send(std::make_pair(make_safe<read_frame>(ogl_, format_desc_.size, std::move(image.get()), std::move(audio)), packet.second));                                 \r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }       \r
+               });             \r
+       }\r
+                                       \r
+       safe_ptr<core::write_frame> create_frame(const void* tag, const core::pixel_format_desc& desc)\r
+       {               \r
+               return make_safe<write_frame>(ogl_, tag, desc);\r
+       }\r
+                               \r
+       void set_blend_mode(int index, blend_mode::type value)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       blend_modes_[index] = value;\r
+               }, high_priority);\r
+       }\r
+\r
+       void clear_blend_mode(int index)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       blend_modes_.erase(index);\r
+               }, high_priority);\r
+       }\r
+\r
+       void clear_blend_modes()\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       blend_modes_.clear();\r
+               }, high_priority);\r
+       }\r
+\r
+       void set_master_volume(float volume)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       audio_mixer_.set_master_volume(volume);\r
+               }, high_priority);\r
+       }\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       tbb::spin_mutex::scoped_lock lock(format_desc_mutex_);\r
+                       format_desc_ = format_desc;\r
+               });\r
+       }\r
+\r
+       core::video_format_desc get_video_format_desc() const // nothrow\r
+       {\r
+               tbb::spin_mutex::scoped_lock lock(format_desc_mutex_);\r
+               return format_desc_;\r
+       }\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info() const\r
+       {\r
+               boost::promise<boost::property_tree::wptree> info;\r
+               info.set_value(boost::property_tree::wptree());\r
+               return info.get_future();\r
+       }\r
+};\r
+       \r
+mixer::mixer(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
+       : impl_(new implementation(graph, target, format_desc, ogl)){}\r
+void mixer::send(const std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>& frames){ impl_->send(frames);}\r
+core::video_format_desc mixer::get_video_format_desc() const { return impl_->get_video_format_desc(); }\r
+safe_ptr<core::write_frame> mixer::create_frame(const void* tag, const core::pixel_format_desc& desc){ return impl_->create_frame(tag, desc); }                \r
+void mixer::set_blend_mode(int index, blend_mode::type value){impl_->set_blend_mode(index, value);}\r
+void mixer::clear_blend_mode(int index) { impl_->clear_blend_mode(index); }\r
+void mixer::clear_blend_modes() { impl_->clear_blend_modes(); }\r
+void mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\r
+void mixer::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
+boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}\r
+}}
\ No newline at end of file
diff --git a/core/mixer/mixer.h b/core/mixer/mixer.h
new file mode 100644 (file)
index 0000000..2ee8241
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "image/blend_modes.h"\r
+\r
+#include "../producer/frame/frame_factory.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/concurrency/target.h>\r
+#include <common/diagnostics/graph.h>\r
+\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <map>\r
+\r
+namespace caspar { \r
+\r
+class executor;\r
+       \r
+namespace core {\r
+\r
+class read_frame;\r
+class write_frame;\r
+class basic_frame;\r
+class ogl_device;\r
+struct frame_transform;\r
+struct pixel_format;\r
+\r
+class mixer : public target<std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>>\r
+                       , public core::frame_factory\r
+{\r
+public:        \r
+       typedef target<std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>> target_t;\r
+\r
+       explicit mixer(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
+               \r
+       // target\r
+\r
+       virtual void send(const std::pair<std::map<int, safe_ptr<basic_frame>>, std::shared_ptr<void>>& frames) override; \r
+               \r
+       // mixer\r
+\r
+       safe_ptr<core::write_frame> create_frame(const void* tag, const core::pixel_format_desc& desc);         \r
+       \r
+       core::video_format_desc get_video_format_desc() const; // nothrow\r
+       void set_video_format_desc(const video_format_desc& format_desc);\r
+       \r
+       void set_blend_mode(int index, blend_mode::type value);\r
+       void clear_blend_mode(int index);\r
+       void clear_blend_modes();\r
+\r
+       void set_master_volume(float volume);\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info() const;\r
+       \r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/read_frame.cpp b/core/mixer/read_frame.cpp
new file mode 100644 (file)
index 0000000..9a4b103
--- /dev/null
@@ -0,0 +1,206 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "read_frame.h"\r
+\r
+#include "gpu/fence.h"\r
+#include "gpu/host_buffer.h"   \r
+#include "gpu/ogl_device.h"\r
+\r
+#include <tbb/mutex.h>\r
+\r
+namespace caspar { namespace core {\r
+                                                                                                                                                                                                                                                                                                                       \r
+struct read_frame::implementation : boost::noncopyable\r
+{\r
+       safe_ptr<ogl_device>            ogl_;\r
+       size_t                                          size_;\r
+       safe_ptr<host_buffer>           image_data_;\r
+       tbb::mutex                                      mutex_;\r
+       audio_buffer                            audio_data_;\r
+\r
+public:\r
+       implementation(const safe_ptr<ogl_device>& ogl, size_t size, safe_ptr<host_buffer>&& image_data, audio_buffer&& audio_data) \r
+               : ogl_(ogl)\r
+               , size_(size)\r
+               , image_data_(std::move(image_data))\r
+               , audio_data_(std::move(audio_data)){}  \r
+       \r
+       const boost::iterator_range<const uint8_t*> image_data()\r
+       {\r
+               {\r
+                       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+                       if(!image_data_->data())\r
+                       {\r
+                               image_data_.get()->wait(*ogl_);\r
+                               ogl_->invoke([=]{image_data_.get()->map();}, high_priority);\r
+                       }\r
+               }\r
+\r
+               auto ptr = static_cast<const uint8_t*>(image_data_->data());\r
+               return boost::iterator_range<const uint8_t*>(ptr, ptr + image_data_->size());\r
+       }\r
+       const boost::iterator_range<const int32_t*> audio_data()\r
+       {\r
+               return boost::iterator_range<const int32_t*>(audio_data_.data(), audio_data_.data() + audio_data_.size());\r
+       }\r
+};\r
+\r
+read_frame::read_frame(const safe_ptr<ogl_device>& ogl, size_t size, safe_ptr<host_buffer>&& image_data, audio_buffer&& audio_data) \r
+       : impl_(new implementation(ogl, size, std::move(image_data), std::move(audio_data))){}\r
+read_frame::read_frame(){}\r
+const boost::iterator_range<const uint8_t*> read_frame::image_data()\r
+{\r
+       return impl_ ? impl_->image_data() : boost::iterator_range<const uint8_t*>();\r
+}\r
+\r
+const boost::iterator_range<const int32_t*> read_frame::audio_data()\r
+{\r
+       return impl_ ? impl_->audio_data() : boost::iterator_range<const int32_t*>();\r
+}\r
+\r
+size_t read_frame::image_size() const{return impl_ ? impl_->size_ : 0;}\r
+\r
+//#include <tbb/scalable_allocator.h>\r
+//#include <tbb/parallel_for.h>\r
+//#include <tbb/enumerable_thread_specific.h>\r
+//#define              CACHED_BUFFER_SIZE      4096    \r
+//typedef              unsigned int            UINT;\r
+//\r
+//struct cache_buffer\r
+//{\r
+//     cache_buffer() : data(scalable_aligned_malloc(CACHED_BUFFER_SIZE, 64)){}\r
+//     ~cache_buffer() {scalable_aligned_free(data);}\r
+//     void* data;\r
+//};\r
+//\r
+//void CopyFrame( void * pSrc, void * pDest, UINT width, UINT height, UINT pitch );\r
+//\r
+//void* copy_frame(void* dest, const safe_ptr<read_frame>& frame)\r
+//{\r
+//     auto src                = frame->image_data().begin();\r
+//     auto height             = 720;\r
+//     auto width4             = frame->image_data().size()/height;\r
+//\r
+//     CASPAR_ASSERT(frame->image_data().size() % height == 0);\r
+//                     \r
+//     tbb::affinity_partitioner ap;\r
+//     tbb::parallel_for(tbb::blocked_range<size_t>(0, height), [&](tbb::blocked_range<size_t>& r)\r
+//     {\r
+//             CopyFrame(const_cast<uint8_t*>(src)+r.begin()*width4, reinterpret_cast<uint8_t*>(dest)+r.begin()*width4, width4, r.size(), width4);\r
+//     }, ap);\r
+//\r
+//     return dest;\r
+//}\r
+//\r
+////  CopyFrame( )\r
+////\r
+////  COPIES VIDEO FRAMES FROM USWC MEMORY TO WB SYSTEM MEMORY VIA CACHED BUFFER\r
+////    ASSUMES PITCH IS A MULTIPLE OF 64B CACHE LINE SIZE, WIDTH MAY NOT BE\r
+//// http://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers/\r
+//void CopyFrame( void * pSrc, void * pDest, UINT width, UINT height, UINT pitch )\r
+//{\r
+//     tbb::enumerable_thread_specific<cache_buffer> cache_buffers;\r
+//\r
+//     void *          pCacheBlock = cache_buffers.local().data;\r
+//\r
+//     __m128i         x0, x1, x2, x3;\r
+//     __m128i         *pLoad;\r
+//     __m128i         *pStore;\r
+//     __m128i         *pCache;\r
+//     UINT            x, y, yLoad, yStore;\r
+//     UINT            rowsPerBlock;\r
+//     UINT            width64;\r
+//     UINT            extraPitch;     \r
+//\r
+//     rowsPerBlock = CACHED_BUFFER_SIZE / pitch;\r
+//     width64 = (width + 63) & ~0x03f;\r
+//     extraPitch = (pitch - width64) / 16;\r
+//\r
+//     pLoad  = (__m128i *)pSrc;\r
+//     pStore = (__m128i *)pDest;\r
+//\r
+//     //  COPY THROUGH 4KB CACHED BUFFER\r
+//     for( y = 0; y < height; y += rowsPerBlock  )\r
+//     {\r
+//             //  ROWS LEFT TO COPY AT END\r
+//             if( y + rowsPerBlock > height )\r
+//                     rowsPerBlock = height - y;\r
+//\r
+//             pCache = (__m128i *)pCacheBlock;\r
+//\r
+//             _mm_mfence();                           \r
+//             \r
+//             // LOAD ROWS OF PITCH WIDTH INTO CACHED BLOCK\r
+//             for( yLoad = 0; yLoad < rowsPerBlock; yLoad++ )\r
+//             {\r
+//                     // COPY A ROW, CACHE LINE AT A TIME\r
+//                     for( x = 0; x < pitch; x +=64 )\r
+//                     {\r
+//                             x0 = _mm_stream_load_si128( pLoad +0 );\r
+//                             x1 = _mm_stream_load_si128( pLoad +1 );\r
+//                             x2 = _mm_stream_load_si128( pLoad +2 );\r
+//                             x3 = _mm_stream_load_si128( pLoad +3 );\r
+//\r
+//                             _mm_store_si128( pCache +0,     x0 );\r
+//                             _mm_store_si128( pCache +1, x1 );\r
+//                             _mm_store_si128( pCache +2, x2 );\r
+//                             _mm_store_si128( pCache +3, x3 );\r
+//\r
+//                             pCache += 4;\r
+//                             pLoad += 4;\r
+//                     }\r
+//             }\r
+//\r
+//             _mm_mfence();\r
+//\r
+//             pCache = (__m128i *)pCacheBlock;\r
+//\r
+//             // STORE ROWS OF FRAME WIDTH FROM CACHED BLOCK\r
+//             for( yStore = 0; yStore < rowsPerBlock; yStore++ )\r
+//             {\r
+//                     // copy a row, cache line at a time\r
+//                     for( x = 0; x < width64; x +=64 )\r
+//                     {\r
+//                             x0 = _mm_load_si128( pCache );\r
+//                             x1 = _mm_load_si128( pCache +1 );\r
+//                             x2 = _mm_load_si128( pCache +2 );\r
+//                             x3 = _mm_load_si128( pCache +3 );\r
+//\r
+//                             _mm_stream_si128( pStore,       x0 );\r
+//                             _mm_stream_si128( pStore +1, x1 );\r
+//                             _mm_stream_si128( pStore +2, x2 );\r
+//                             _mm_stream_si128( pStore +3, x3 );\r
+//\r
+//                             pCache += 4;\r
+//                             pStore += 4;\r
+//                     }\r
+//\r
+//                     pCache += extraPitch;\r
+//                     pStore += extraPitch;\r
+//             }\r
+//     }\r
+//}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/read_frame.h b/core/mixer/read_frame.h
new file mode 100644 (file)
index 0000000..93c344c
--- /dev/null
@@ -0,0 +1,56 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/mixer/audio/audio_mixer.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
+\r
+#include <cstdint>\r
+#include <memory>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class host_buffer;\r
+class ogl_device;\r
+\r
+class read_frame : boost::noncopyable\r
+{\r
+public:\r
+       read_frame();\r
+       read_frame(const safe_ptr<ogl_device>& ogl, size_t size, safe_ptr<host_buffer>&& image_data, audio_buffer&& audio_data);\r
+\r
+       virtual const boost::iterator_range<const uint8_t*> image_data();\r
+       virtual const boost::iterator_range<const int32_t*> audio_data();\r
+\r
+       virtual size_t image_size() const;\r
+               \r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/write_frame.cpp b/core/mixer/write_frame.cpp
new file mode 100644 (file)
index 0000000..93889ad
--- /dev/null
@@ -0,0 +1,141 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "write_frame.h"\r
+\r
+#include "gpu/ogl_device.h"\r
+#include "gpu/host_buffer.h"\r
+#include "gpu/device_buffer.h"\r
+\r
+#include <core/producer/frame/frame_visitor.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace core {\r
+                                                                                                                                                                                                                                                                                                                       \r
+struct write_frame::implementation\r
+{                              \r
+       std::shared_ptr<ogl_device>                                     ogl_;\r
+       std::vector<std::shared_ptr<host_buffer>>       buffers_;\r
+       std::vector<safe_ptr<device_buffer>>            textures_;\r
+       audio_buffer                                                            audio_data_;\r
+       const core::pixel_format_desc                           desc_;\r
+       const void*                                                                     tag_;\r
+       core::field_mode::type                                          mode_;\r
+\r
+       implementation(const void* tag)\r
+               : tag_(tag)\r
+       {\r
+       }\r
+\r
+       implementation(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc) \r
+               : ogl_(ogl)\r
+               , desc_(desc)\r
+               , tag_(tag)\r
+               , mode_(core::field_mode::progressive)\r
+       {\r
+               std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(buffers_), [&](const core::pixel_format_desc::plane& plane)\r
+               {\r
+                       return ogl_->create_host_buffer(plane.size, host_buffer::write_only);\r
+               });\r
+               std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(textures_), [&](const core::pixel_format_desc::plane& plane)\r
+               {\r
+                       return ogl_->create_device_buffer(plane.width, plane.height, plane.channels);   \r
+               });\r
+       }\r
+                       \r
+       void accept(write_frame& self, core::frame_visitor& visitor)\r
+       {\r
+               visitor.begin(self);\r
+               visitor.visit(self);\r
+               visitor.end();\r
+       }\r
+\r
+       boost::iterator_range<uint8_t*> image_data(size_t index)\r
+       {\r
+               if(index >= buffers_.size() || !buffers_[index]->data())\r
+                       return boost::iterator_range<uint8_t*>();\r
+               auto ptr = static_cast<uint8_t*>(buffers_[index]->data());\r
+               return boost::iterator_range<uint8_t*>(ptr, ptr+buffers_[index]->size());\r
+       }\r
+       \r
+       void commit()\r
+       {\r
+               for(size_t n = 0; n < buffers_.size(); ++n)\r
+                       commit(n);\r
+       }\r
+\r
+       void commit(size_t plane_index)\r
+       {\r
+               if(plane_index >= buffers_.size())\r
+                       return;\r
+                               \r
+               auto buffer = std::move(buffers_[plane_index]); // Release buffer once done.\r
+\r
+               if(!buffer)\r
+                       return;\r
+\r
+               auto texture = textures_.at(plane_index);\r
+               \r
+               ogl_->begin_invoke([=]\r
+               {                       \r
+                       buffer->unmap();\r
+                       buffer->bind();\r
+                       texture->begin_read();\r
+                       buffer->unbind();\r
+               }, high_priority);\r
+       }\r
+};\r
+       \r
+write_frame::write_frame(const void* tag) : impl_(new implementation(tag)){}\r
+write_frame::write_frame(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc) \r
+       : impl_(new implementation(ogl, tag, desc)){}\r
+write_frame::write_frame(const write_frame& other) : impl_(new implementation(*other.impl_)){}\r
+write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
+write_frame& write_frame::operator=(const write_frame& other)\r
+{\r
+       basic_frame temp(other);\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+write_frame& write_frame::operator=(write_frame&& other)\r
+{\r
+       write_frame temp(std::move(other));\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+void write_frame::swap(write_frame& other){impl_.swap(other.impl_);}\r
+\r
+boost::iterator_range<uint8_t*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
+audio_buffer& write_frame::audio_data() { return impl_->audio_data_; }\r
+const void* write_frame::tag() const {return impl_->tag_;}\r
+const core::pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
+const std::vector<safe_ptr<device_buffer>>& write_frame::get_textures() const{return impl_->textures_;}\r
+void write_frame::commit(size_t plane_index){impl_->commit(plane_index);}\r
+void write_frame::commit(){impl_->commit();}\r
+void write_frame::set_type(const field_mode::type& mode){impl_->mode_ = mode;}\r
+core::field_mode::type write_frame::get_type() const{return impl_->mode_;}\r
+void write_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/mixer/write_frame.h b/core/mixer/write_frame.h
new file mode 100644 (file)
index 0000000..7c75d02
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/video_format.h>\r
+#include <core/mixer/audio/audio_mixer.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
+\r
+#include <cstdint>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class device_buffer;\r
+struct frame_visitor;\r
+struct pixel_format_desc;\r
+class ogl_device;      \r
+\r
+class write_frame : public core::basic_frame, boost::noncopyable\r
+{\r
+public:        \r
+       explicit write_frame(const void* tag);\r
+       explicit write_frame(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc);\r
+\r
+       write_frame(const write_frame& other);\r
+       write_frame(write_frame&& other);\r
+\r
+       write_frame& operator=(const write_frame& other);\r
+       write_frame& operator=(write_frame&& other);\r
+                       \r
+       // basic_frame\r
+\r
+       virtual void accept(frame_visitor& visitor) override;\r
+\r
+       // write _frame\r
+\r
+       void swap(write_frame& other);\r
+                       \r
+       boost::iterator_range<uint8_t*> image_data(size_t plane_index = 0);     \r
+       audio_buffer& audio_data();\r
+       \r
+       void commit(uint32_t plane_index);\r
+       void commit();\r
+       \r
+       void set_type(const field_mode::type& mode);\r
+       field_mode::type get_type() const;\r
+       \r
+       const void* tag() const;\r
+\r
+       const core::pixel_format_desc& get_pixel_format_desc() const;\r
+       \r
+private:\r
+       friend class image_mixer;\r
+       \r
+       const std::vector<safe_ptr<device_buffer>>& get_textures() const;\r
+\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/channel/channel_producer.cpp b/core/producer/channel/channel_producer.cpp
new file mode 100644 (file)
index 0000000..6d3bdb2
--- /dev/null
@@ -0,0 +1,217 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "channel_producer.h"\r
+\r
+#include "../../consumer/frame_consumer.h"\r
+#include "../../consumer/output.h"\r
+#include "../../video_channel.h"\r
+\r
+#include "../frame/basic_frame.h"\r
+#include "../frame/frame_factory.h"\r
+#include "../../mixer/write_frame.h"\r
+#include "../../mixer/read_frame.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/concurrency/future_util.h>\r\r
+#include <tbb/concurrent_queue.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class channel_consumer : public frame_consumer\r
+{      \r
+       tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>>      frame_buffer_;\r
+       core::video_format_desc                                                                         format_desc_;\r
+       int                                                                                                                     channel_index_;\r
+       tbb::atomic<bool>                                                                                       is_running_;\r
+\r
+public:\r
+       channel_consumer() \r
+       {\r
+               is_running_ = true;\r
+               frame_buffer_.set_capacity(3);\r
+       }\r
+\r
+       ~channel_consumer()\r
+       {\r
+               stop();\r
+       }\r
+\r
+       // frame_consumer\r
+\r
+       virtual boost::unique_future<bool> send(const safe_ptr<read_frame>& frame) override\r
+       {\r
+               frame_buffer_.try_push(frame);\r
+               return caspar::wrap_as_future(is_running_.load());\r
+       }\r
+\r
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               format_desc_    = format_desc;\r
+               channel_index_  = channel_index;\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"[channel-consumer|" + boost::lexical_cast<std::wstring>(channel_index_) + L"]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"channel-consumer");\r
+               info.add(L"channel-index", channel_index_);\r
+               return info;\r
+       }\r
+       \r
+       virtual bool has_synchronization_clock() const override\r
+       {\r
+               return false;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return 1;\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 78500 + channel_index_;\r
+       }\r
+\r
+       // channel_consumer\r
+\r
+       void stop()\r
+       {\r
+               is_running_ = false;\r
+               frame_buffer_.try_push(make_safe<read_frame>());\r
+       }\r
+       \r
+       const core::video_format_desc& get_video_format_desc()\r
+       {\r
+               return format_desc_;\r
+       }\r
+\r
+       std::shared_ptr<read_frame> receive()\r
+       {\r
+               if(!is_running_)\r
+                       return make_safe<read_frame>();\r
+               std::shared_ptr<read_frame> frame;\r
+               frame_buffer_.try_pop(frame);\r
+               return frame;\r
+       }\r
+};\r
+       \r
+class channel_producer : public frame_producer\r
+{\r
+       const safe_ptr<frame_factory>           frame_factory_;\r
+       const safe_ptr<channel_consumer>        consumer_;\r
+\r
+       std::queue<safe_ptr<basic_frame>>       frame_buffer_;\r
+       safe_ptr<basic_frame>                           last_frame_;\r
+       uint64_t                                                        frame_number_;\r
+\r
+public:\r
+       explicit channel_producer(const safe_ptr<frame_factory>& frame_factory, const safe_ptr<video_channel>& channel) \r
+               : frame_factory_(frame_factory)\r
+               , consumer_(make_safe<channel_consumer>())\r
+               , last_frame_(basic_frame::empty())\r
+               , frame_number_(0)\r
+       {\r
+               channel->output()->add(consumer_);\r
+               CASPAR_LOG(info) << print() << L" Initialized";\r
+       }\r
+\r
+       ~channel_producer()\r
+       {\r
+               consumer_->stop();\r
+               CASPAR_LOG(info) << print() << L" Uninitialized";\r
+       }\r
+\r
+       // frame_producer\r
+                       \r
+       virtual safe_ptr<basic_frame> receive(int) override\r
+       {\r
+               auto format_desc = consumer_->get_video_format_desc();\r
+\r
+               if(frame_buffer_.size() > 1)\r
+               {\r
+                       auto frame = frame_buffer_.front();\r
+                       frame_buffer_.pop();\r
+                       return last_frame_ = frame;\r
+               }\r
+               \r
+               auto read_frame = consumer_->receive();\r
+               if(!read_frame || read_frame->image_data().empty())\r
+                       return basic_frame::late();             \r
+\r
+               frame_number_++;\r
+               \r
+               core::pixel_format_desc desc;\r
+               bool double_speed       = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01;         \r
+               bool half_speed         = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
+\r
+               if(half_speed && frame_number_ % 2 == 0) // Skip frame\r
+                       return receive(0);\r
+\r
+               desc.pix_fmt = core::pixel_format::bgra;\r
+               desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
+               auto frame = frame_factory_->create_frame(this, desc);\r
+\r
+               fast_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
+               frame->commit();\r
+\r
+               frame_buffer_.push(frame);      \r
+               \r
+               if(double_speed)        \r
+                       frame_buffer_.push(frame);\r
+\r
+               return receive(0);\r
+       }       \r
+\r
+       virtual safe_ptr<basic_frame> last_frame() const override\r
+       {\r
+               return last_frame_; \r
+       }       \r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"channel[]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"channel-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel)\r
+{\r
+       return create_producer_print_proxy(\r
+                       make_safe<channel_producer>(frame_factory, channel));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/channel/channel_producer.h b/core/producer/channel/channel_producer.h
new file mode 100644 (file)
index 0000000..6d39ce6
--- /dev/null
@@ -0,0 +1,36 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class video_channel;\r
+struct frame_factory;\r
+\r
+safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel);\r
+\r
+}}\r
diff --git a/core/producer/color/color_producer.cpp b/core/producer/color/color_producer.cpp
new file mode 100644 (file)
index 0000000..8582a27
--- /dev/null
@@ -0,0 +1,151 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "color_producer.h"\r
+\r
+#include "../frame/basic_frame.h"\r
+#include "../frame/frame_factory.h"\r
+#include "../../mixer/write_frame.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+\r
+#include <sstream>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class color_producer : public frame_producer\r
+{\r
+       safe_ptr<basic_frame> frame_;\r
+       const std::wstring color_str_;\r
+\r
+public:\r
+       explicit color_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& color) \r
+               : color_str_(color)\r
+               , frame_(create_color_frame(this, frame_factory, color))\r
+       {}\r
+\r
+       // frame_producer\r
+                       \r
+       virtual safe_ptr<basic_frame> receive(int) override\r
+       {\r
+               return frame_;\r
+       }       \r
+\r
+       virtual safe_ptr<basic_frame> last_frame() const override\r
+       {\r
+               return frame_; \r
+       }       \r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"color[" + color_str_ + L"]";\r
+       }\r
+\r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"color-producer");\r
+               info.add(L"color", color_str_);\r
+               return info;\r
+       }\r
+};\r
+\r
+std::wstring get_hex_color(const std::wstring& str)\r
+{\r
+       if(str.at(0) == '#')\r
+               return str.length() == 7 ? L"#FF" + str.substr(1) : str;\r
+       \r
+       if(boost::iequals(str, L"EMPTY"))\r
+               return L"#00000000";\r
+\r
+       if(boost::iequals(str, L"BLACK"))\r
+               return L"#FF000000";\r
+       \r
+       if(boost::iequals(str, L"WHITE"))\r
+               return L"#FFFFFFFF";\r
+       \r
+       if(boost::iequals(str, L"RED"))\r
+               return L"#FFFF0000";\r
+       \r
+       if(boost::iequals(str, L"GREEN"))\r
+               return L"#FF00FF00";\r
+       \r
+       if(boost::iequals(str, L"BLUE"))\r
+               return L"#FF0000FF";    \r
+       \r
+       if(boost::iequals(str, L"ORANGE"))\r
+               return L"#FFFFA500";    \r
+       \r
+       if(boost::iequals(str, L"YELLOW"))\r
+               return L"#FFFFFF00";\r
+       \r
+       if(boost::iequals(str, L"BROWN"))\r
+               return L"#FFA52A2A";\r
+       \r
+       if(boost::iequals(str, L"GRAY"))\r
+               return L"#FF808080";\r
+       \r
+       if(boost::iequals(str, L"TEAL"))\r
+               return L"#FF008080";\r
+       \r
+       return str;\r
+}\r
+\r
+safe_ptr<frame_producer> create_color_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 0)\r
+               return core::frame_producer::empty();\r
+\r
+       auto color2 = get_hex_color(params[0]);\r
+       if(color2.length() != 9 || color2[0] != '#')\r
+               return core::frame_producer::empty();\r
+\r
+       return create_producer_print_proxy(\r
+                       make_safe<color_producer>(frame_factory, color2));\r
+}\r
+safe_ptr<core::write_frame> create_color_frame(void* tag, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& color)\r
+{\r
+       auto color2 = get_hex_color(color);\r
+       if(color2.length() != 9 || color2[0] != '#')\r
+               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("color") << arg_value_info(narrow(color2)) << msg_info("Invalid color."));\r
+       \r
+       core::pixel_format_desc desc;\r
+       desc.pix_fmt = pixel_format::bgra;\r
+       desc.planes.push_back(core::pixel_format_desc::plane(1, 1, 4));\r
+       auto frame = frame_factory->create_frame(tag, desc);\r
+               \r
+       // Read color from hex-string and write to frame pixel.\r
+\r
+       auto& value = *reinterpret_cast<uint32_t*>(frame->image_data().begin());\r
+       std::wstringstream str(color2.substr(1));\r
+       if(!(str >> std::hex >> value) || !str.eof())\r
+               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("color") << arg_value_info(narrow(color2)) << msg_info("Invalid color."));\r
+\r
+       frame->commit();\r
+               \r
+       return frame;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/color/color_producer.h b/core/producer/color/color_producer.h
new file mode 100644 (file)
index 0000000..56bde5a
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class write_frame;\r
+struct frame_factory;\r
+\r
+safe_ptr<frame_producer> create_color_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::write_frame> create_color_frame(void* tag, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& color);\r
+\r
+}}\r
diff --git a/core/producer/frame/basic_frame.cpp b/core/producer/frame/basic_frame.cpp
new file mode 100644 (file)
index 0000000..ce4f773
--- /dev/null
@@ -0,0 +1,158 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "basic_frame.h"\r
+\r
+#include "frame_transform.h"\r
+#include "../../video_format.h"\r
+\r
+#include <boost/foreach.hpp>\r
+\r
+namespace caspar { namespace core {\r
+                                                                                                                                                                                                                                                                                                               \r
+struct basic_frame::implementation\r
+{              \r
+       std::vector<safe_ptr<basic_frame>> frames_;\r
+\r
+       frame_transform frame_transform_;       \r
+       \r
+public:\r
+       implementation(const std::vector<safe_ptr<basic_frame>>& frames) : frames_(frames) \r
+       {\r
+       }\r
+       implementation(std::vector<safe_ptr<basic_frame>>&& frames) : frames_(std::move(frames))\r
+       {\r
+       }\r
+       implementation(safe_ptr<basic_frame>&& frame) \r
+       {\r
+               frames_.push_back(std::move(frame));\r
+       }\r
+       implementation(const safe_ptr<basic_frame>& frame)              \r
+       { \r
+               frames_.push_back(frame);\r
+       }\r
+       \r
+       void accept(basic_frame& self, frame_visitor& visitor)\r
+       {\r
+               visitor.begin(self);\r
+               BOOST_FOREACH(auto frame, frames_)\r
+                       frame->accept(visitor);\r
+               visitor.end();\r
+       }       \r
+};\r
+       \r
+basic_frame::basic_frame() : impl_(new implementation(std::vector<safe_ptr<basic_frame>>())){}\r
+basic_frame::basic_frame(const std::vector<safe_ptr<basic_frame>>& frames) : impl_(new implementation(frames)){}\r
+basic_frame::basic_frame(const basic_frame& other) : impl_(new implementation(*other.impl_)){}\r
+basic_frame::basic_frame(std::vector<safe_ptr<basic_frame>>&& frames) : impl_(new implementation(frames)){}\r
+basic_frame::basic_frame(const safe_ptr<basic_frame>& frame) : impl_(new implementation(frame)){}\r
+basic_frame::basic_frame(safe_ptr<basic_frame>&& frame)  : impl_(new implementation(std::move(frame))){}\r
+basic_frame::basic_frame(basic_frame&& other) : impl_(std::move(other.impl_)){}\r
+basic_frame& basic_frame::operator=(const basic_frame& other)\r
+{\r
+       basic_frame temp(other);\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+basic_frame& basic_frame::operator=(basic_frame&& other)\r
+{\r
+       basic_frame temp(std::move(other));\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+void basic_frame::swap(basic_frame& other){impl_.swap(other.impl_);}\r
+\r
+const frame_transform& basic_frame::get_frame_transform() const { return impl_->frame_transform_;}\r
+frame_transform& basic_frame::get_frame_transform() { return impl_->frame_transform_;}\r
+void basic_frame::accept(frame_visitor& visitor){impl_->accept(*this, visitor);}\r
+\r
+safe_ptr<basic_frame> basic_frame::interlace(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2, field_mode::type mode)\r
+{                              \r
+       if(frame1 == basic_frame::eof() || frame2 == basic_frame::eof())\r
+               return basic_frame::eof();\r
+\r
+       if(frame1 == basic_frame::empty() && frame2 == basic_frame::empty())\r
+               return basic_frame::empty();\r
+       \r
+       if(frame1 == frame2 || mode == field_mode::progressive)\r
+               return frame2;\r
+\r
+       auto my_frame1 = make_safe<basic_frame>(frame1);\r
+       auto my_frame2 = make_safe<basic_frame>(frame2);\r
+       if(mode == field_mode::upper)\r
+       {\r
+               my_frame1->get_frame_transform().field_mode = field_mode::upper;        \r
+               my_frame2->get_frame_transform().field_mode = field_mode::lower;        \r
+       }                                                                        \r
+       else                                                             \r
+       {                                                                        \r
+               my_frame1->get_frame_transform().field_mode = field_mode::lower;        \r
+               my_frame2->get_frame_transform().field_mode = field_mode::upper;        \r
+       }\r
+\r
+       std::vector<safe_ptr<basic_frame>> frames;\r
+       frames.push_back(my_frame1);\r
+       frames.push_back(my_frame2);\r
+       return make_safe<basic_frame>(std::move(frames));\r
+}\r
+\r
+safe_ptr<basic_frame> basic_frame::combine(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2)\r
+{      \r
+       if(frame1 == basic_frame::eof() || frame2 == basic_frame::eof())\r
+               return basic_frame::eof();\r
+       \r
+       if(frame1 == basic_frame::empty() && frame2 == basic_frame::empty())\r
+               return basic_frame::empty();\r
+\r
+       std::vector<safe_ptr<basic_frame>> frames;\r
+       frames.push_back(frame1);\r
+       frames.push_back(frame2);\r
+       return make_safe<basic_frame>(std::move(frames));\r
+}\r
+\r
+safe_ptr<basic_frame> basic_frame::fill_and_key(const safe_ptr<basic_frame>& fill, const safe_ptr<basic_frame>& key)\r
+{      \r
+       if(fill == basic_frame::eof() || key == basic_frame::eof())\r
+               return basic_frame::eof();\r
+\r
+       if(fill == basic_frame::empty() || key == basic_frame::empty())\r
+               return basic_frame::empty();\r
+\r
+       std::vector<safe_ptr<basic_frame>> frames;\r
+       key->get_frame_transform().is_key = true;\r
+       frames.push_back(key);\r
+       frames.push_back(fill);\r
+       return make_safe<basic_frame>(std::move(frames));\r
+}\r
+\r
+safe_ptr<basic_frame> disable_audio(const safe_ptr<basic_frame>& frame)\r
+{\r
+       if(frame == basic_frame::empty())\r
+               return frame;\r
+\r
+       basic_frame frame2 = frame;\r
+       frame2.get_frame_transform().volume = 0.0;\r
+       return make_safe<basic_frame>(std::move(frame2));\r
+}\r
+       \r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/basic_frame.h b/core/producer/frame/basic_frame.h
new file mode 100644 (file)
index 0000000..3b7a44d
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "frame_visitor.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/range/iterator_range.hpp>\r
+\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct frame_transform;\r
+\r
+class basic_frame\r
+{\r
+public:\r
+       basic_frame();  \r
+       basic_frame(const basic_frame& other);\r
+       basic_frame(basic_frame&& other);\r
+       virtual ~basic_frame(){}\r
+\r
+       basic_frame(const safe_ptr<basic_frame>& frame);\r
+       basic_frame(safe_ptr<basic_frame>&& frame);\r
+       basic_frame(const std::vector<safe_ptr<basic_frame>>& frames);\r
+       basic_frame(std::vector<safe_ptr<basic_frame>>&& frames);\r
+\r
+       basic_frame& operator=(const basic_frame& other);\r
+       basic_frame& operator=(basic_frame&& other);\r
+       \r
+       void swap(basic_frame& other);\r
+\r
+       const frame_transform& get_frame_transform() const;\r
+       frame_transform& get_frame_transform();\r
+                               \r
+       static safe_ptr<basic_frame> interlace(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2, field_mode::type mode);\r
+       static safe_ptr<basic_frame> combine(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2);\r
+       static safe_ptr<basic_frame> fill_and_key(const safe_ptr<basic_frame>& fill, const safe_ptr<basic_frame>& key);\r
+               \r
+       static const safe_ptr<basic_frame>& eof()\r
+       {\r
+               static safe_ptr<basic_frame> frame = make_safe<basic_frame>();\r
+               return frame;\r
+       }\r
+\r
+       static const safe_ptr<basic_frame>& empty()\r
+       {\r
+               static safe_ptr<basic_frame> frame = make_safe<basic_frame>();\r
+               return frame;\r
+       }\r
+\r
+       static const safe_ptr<basic_frame>& late()\r
+       {\r
+               static safe_ptr<basic_frame> frame = make_safe<basic_frame>();\r
+               return frame;\r
+       }\r
+       \r
+       virtual void accept(frame_visitor& visitor);\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+safe_ptr<basic_frame> disable_audio(const safe_ptr<basic_frame>& frame);\r
+\r
+inline bool is_concrete_frame(const safe_ptr<basic_frame>& frame)\r
+{\r
+       return frame != basic_frame::empty() && frame != basic_frame::eof() && frame != basic_frame::late();\r
+}\r
+\r
+inline bool is_concrete_frame(const std::shared_ptr<basic_frame>& frame)\r
+{\r
+       return frame != nullptr && frame.get() != basic_frame::empty().get() && frame.get() != basic_frame::eof().get() && frame.get() != basic_frame::late().get();\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/frame_factory.h b/core/producer/frame/frame_factory.h
new file mode 100644 (file)
index 0000000..7656fee
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "pixel_format.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class write_frame;\r
+struct pixel_format_desc;\r
+struct video_format_desc;\r
+               \r
+struct frame_factory : boost::noncopyable\r
+{\r
+       virtual ~frame_factory(){}\r
+       virtual safe_ptr<write_frame> create_frame(const void* video_stream_tag, const pixel_format_desc& desc) = 0;    \r
+       \r
+       virtual video_format_desc get_video_format_desc() const = 0; // nothrow\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/frame_transform.cpp b/core/producer/frame/frame_transform.cpp
new file mode 100644 (file)
index 0000000..4532aff
--- /dev/null
@@ -0,0 +1,125 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "frame_transform.h"\r
+\r
+#include <common/utility/assert.h>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+frame_transform::frame_transform() \r
+       : volume(1.0)\r
+       , opacity(1.0)\r
+       , brightness(1.0)\r
+       , contrast(1.0)\r
+       , saturation(1.0)\r
+       , field_mode(field_mode::progressive)\r
+       , is_key(false)\r
+       , is_mix(false)\r
+{\r
+       std::fill(fill_translation.begin(), fill_translation.end(), 0.0);\r
+       std::fill(fill_scale.begin(), fill_scale.end(), 1.0);\r
+       std::fill(clip_translation.begin(), clip_translation.end(), 0.0);\r
+       std::fill(clip_scale.begin(), clip_scale.end(), 1.0);\r
+}\r
+\r
+frame_transform& frame_transform::operator*=(const frame_transform &other)\r
+{\r
+       volume                                  *= other.volume;\r
+       opacity                                 *= other.opacity;       \r
+       brightness                              *= other.brightness;\r
+       contrast                                *= other.contrast;\r
+       saturation                              *= other.saturation;\r
+       fill_translation[0]             += other.fill_translation[0]*fill_scale[0];\r
+       fill_translation[1]             += other.fill_translation[1]*fill_scale[1];\r
+       fill_scale[0]                   *= other.fill_scale[0];\r
+       fill_scale[1]                   *= other.fill_scale[1];\r
+       clip_translation[0]             += other.clip_translation[0]*clip_scale[0];\r
+       clip_translation[1]             += other.clip_translation[1]*clip_scale[1];\r
+       clip_scale[0]                   *= other.clip_scale[0];\r
+       clip_scale[1]                   *= other.clip_scale[1];\r
+       levels.min_input                 = std::max(levels.min_input,  other.levels.min_input);\r
+       levels.max_input                 = std::min(levels.max_input,  other.levels.max_input); \r
+       levels.min_output                = std::max(levels.min_output, other.levels.min_output);\r
+       levels.max_output                = std::min(levels.max_output, other.levels.max_output);\r
+       levels.gamma                    *= other.levels.gamma;\r
+       field_mode                               = static_cast<field_mode::type>(field_mode & other.field_mode);\r
+       is_key                                  |= other.is_key;\r
+       is_mix                                  |= other.is_mix;\r
+       return *this;\r
+}\r
+\r
+frame_transform frame_transform::operator*(const frame_transform &other) const\r
+{\r
+       return frame_transform(*this) *= other;\r
+}\r
+\r
+frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener)\r
+{      \r
+       auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener)\r
+       {\r
+               return tweener(time, source, dest-source, duration);\r
+       };\r
+       \r
+       frame_transform result; \r
+       result.volume                           = do_tween(time, source.volume,                                 dest.volume,                            duration, tweener);\r
+       result.brightness                       = do_tween(time, source.brightness,                             dest.brightness,                        duration, tweener);\r
+       result.contrast                         = do_tween(time, source.contrast,                               dest.contrast,                          duration, tweener);\r
+       result.saturation                       = do_tween(time, source.saturation,                             dest.saturation,                        duration, tweener);\r
+       result.opacity                          = do_tween(time, source.opacity,                                dest.opacity,                           duration, tweener);     \r
+       result.fill_translation[0]      = do_tween(time, source.fill_translation[0],    dest.fill_translation[0],       duration, tweener), \r
+       result.fill_translation[1]      = do_tween(time, source.fill_translation[1],    dest.fill_translation[1],       duration, tweener);             \r
+       result.fill_scale[0]            = do_tween(time, source.fill_scale[0],                  dest.fill_scale[0],                     duration, tweener), \r
+       result.fill_scale[1]            = do_tween(time, source.fill_scale[1],                  dest.fill_scale[1],                     duration, tweener);     \r
+       result.clip_translation[0]      = do_tween(time, source.clip_translation[0],    dest.clip_translation[0],       duration, tweener), \r
+       result.clip_translation[1]      = do_tween(time, source.clip_translation[1],    dest.clip_translation[1],       duration, tweener);             \r
+       result.clip_scale[0]            = do_tween(time, source.clip_scale[0],                  dest.clip_scale[0],                     duration, tweener), \r
+       result.clip_scale[1]            = do_tween(time, source.clip_scale[1],                  dest.clip_scale[1],                     duration, tweener);\r
+       result.levels.max_input         = do_tween(time, source.levels.max_input,               dest.levels.max_input,          duration, tweener);\r
+       result.levels.min_input         = do_tween(time, source.levels.min_input,               dest.levels.min_input,          duration, tweener);     \r
+       result.levels.max_output        = do_tween(time, source.levels.max_output,              dest.levels.max_output,         duration, tweener);\r
+       result.levels.min_output        = do_tween(time, source.levels.min_output,              dest.levels.min_output,         duration, tweener);\r
+       result.levels.gamma                     = do_tween(time, source.levels.gamma,                   dest.levels.gamma,                      duration, tweener);\r
+       result.field_mode                       = static_cast<field_mode::type>(source.field_mode & dest.field_mode);\r
+       result.is_key                           = source.is_key | dest.is_key;\r
+       result.is_mix                           = source.is_mix | dest.is_mix;\r
+       \r
+       return result;\r
+}\r
+\r
+bool operator<(const frame_transform& lhs, const frame_transform& rhs)\r
+{\r
+       return memcmp(&lhs, &rhs, sizeof(frame_transform)) < 0;\r
+}\r
+\r
+bool operator==(const frame_transform& lhs, const frame_transform& rhs)\r
+{\r
+       return memcmp(&lhs, &rhs, sizeof(frame_transform)) == 0;\r
+}\r
+\r
+bool operator!=(const frame_transform& lhs, const frame_transform& rhs)\r
+{\r
+       return !(lhs == rhs);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/frame_transform.h b/core/producer/frame/frame_transform.h
new file mode 100644 (file)
index 0000000..e2547b7
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/utility/tweener.h>\r
+#include <core/video_format.h>\r
+\r
+#include <boost/array.hpp>\r
+#include <type_traits>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct pixel_format_desc;\r
+               \r
+struct levels\r
+{\r
+       levels() \r
+               : min_input(0.0)\r
+               , max_input(1.0)\r
+               , gamma(1.0)\r
+               , min_output(0.0)\r
+               , max_output(1.0)\r
+       {               \r
+       }\r
+       double min_input;\r
+       double max_input;\r
+       double gamma;\r
+       double min_output;\r
+       double max_output;\r
+};\r
+\r
+struct frame_transform \r
+{\r
+public:\r
+\r
+       frame_transform();\r
+\r
+       double                                  volume;\r
+       double                                  opacity;\r
+       double                                  contrast;\r
+       double                                  brightness;\r
+       double                                  saturation;\r
+       boost::array<double, 2> fill_translation; \r
+       boost::array<double, 2> fill_scale; \r
+       boost::array<double, 2> clip_translation;  \r
+       boost::array<double, 2> clip_scale;  \r
+       levels                                  levels;\r
+\r
+       field_mode::type                field_mode;\r
+       bool                                    is_key;\r
+       bool                                    is_mix;\r
+       \r
+       frame_transform& frame_transform::operator*=(const frame_transform &other);\r
+       frame_transform frame_transform::operator*(const frame_transform &other) const;\r
+};\r
+\r
+frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener);\r
+\r
+bool operator<(const frame_transform& lhs, const frame_transform& rhs);\r
+bool operator==(const frame_transform& lhs, const frame_transform& rhs);\r
+bool operator!=(const frame_transform& lhs, const frame_transform& rhs);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/frame_visitor.h b/core/producer/frame/frame_visitor.h
new file mode 100644 (file)
index 0000000..66d0b20
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar{ namespace core{\r
+\r
+class basic_frame;\r
+class write_frame;\r
+\r
+struct frame_visitor\r
+{\r
+       virtual ~frame_visitor(){}\r
+       virtual void begin(basic_frame& frame) = 0;\r
+       virtual void end() = 0;\r
+       virtual void visit(write_frame& frame) = 0;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame/pixel_format.h b/core/producer/frame/pixel_format.h
new file mode 100644 (file)
index 0000000..5e62ff1
--- /dev/null
@@ -0,0 +1,76 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+               \r
+struct pixel_format\r
+{\r
+       enum type\r
+       {\r
+               gray = 0,\r
+               bgra,\r
+               rgba,\r
+               argb,\r
+               abgr,\r
+               ycbcr,\r
+               ycbcra,\r
+               luma,\r
+               count,\r
+               invalid\r
+       };\r
+};\r
+\r
+struct pixel_format_desc\r
+{\r
+       struct plane\r
+       {\r
+               size_t linesize;\r
+               size_t width;\r
+               size_t height;\r
+               size_t size;\r
+               size_t channels;\r
+\r
+               plane() \r
+                       : linesize(0)\r
+                       , width(0)\r
+                       , height(0)\r
+                       , size(0)\r
+                       , channels(0){}\r
+\r
+               plane(size_t width, size_t height, size_t channels)\r
+                       : linesize(width*channels)\r
+                       , width(width)\r
+                       , height(height)\r
+                       , size(width*height*channels)\r
+                       , channels(channels){}\r
+       };\r
+\r
+       pixel_format_desc() : pix_fmt(pixel_format::invalid){}\r
+       \r
+       pixel_format::type pix_fmt;\r
+       std::vector<plane> planes;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp
new file mode 100644 (file)
index 0000000..02cc30f
--- /dev/null
@@ -0,0 +1,337 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "frame_producer.h"\r
+#include "frame/basic_frame.h"\r
+#include "frame/frame_transform.h"\r
+\r
+#include "color/color_producer.h"\r
+#include "playlist/playlist_producer.h"\r
+#include "separated/separated_producer.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/move_on_copy.h>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+std::vector<const producer_factory_t> g_factories;\r
+std::vector<const producer_factory_t> g_thumbnail_factories;\r
+       \r
+class destroy_producer_proxy : public frame_producer\r
+{      \r
+       std::unique_ptr<std::shared_ptr<frame_producer>> producer_;\r
+public:\r
+       destroy_producer_proxy(safe_ptr<frame_producer>&& producer) \r
+               : producer_(new std::shared_ptr<frame_producer>(std::move(producer)))\r
+       {\r
+       }\r
+\r
+       ~destroy_producer_proxy()\r
+       {               \r
+               static auto destroyers = std::make_shared<tbb::concurrent_bounded_queue<std::shared_ptr<executor>>>();\r
+               static tbb::atomic<int> destroyer_count;\r
+\r
+               try\r
+               {\r
+                       std::shared_ptr<executor> destroyer;\r
+                       if(!destroyers->try_pop(destroyer))\r
+                       {\r
+                               destroyer.reset(new executor(L"destroyer"));\r
+                               destroyer->set_priority_class(below_normal_priority_class);\r
+                               if(++destroyer_count > 16)\r
+                                       CASPAR_LOG(warning) << L"Potential destroyer dead-lock detected.";\r
+                               CASPAR_LOG(trace) << "Created destroyer: " << destroyer_count;\r
+                       }\r
+                               \r
+                       auto producer = producer_.release();\r
+                       auto pool         = destroyers;\r
+                       destroyer->begin_invoke([=]\r
+                       {\r
+                               std::unique_ptr<std::shared_ptr<frame_producer>> producer2(producer);\r
+\r
+                               auto str = (*producer2)->print();\r
+                               try\r
+                               {\r
+                                       if(!producer->unique())\r
+                                               CASPAR_LOG(trace) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count();\r
+                                       else\r
+                                               CASPAR_LOG(trace) << str << L" Destroying on asynchronous destruction thread.";\r
+                               }\r
+                               catch(...){}\r
+                                                               \r
+                               producer2.reset();\r
+                               pool->push(destroyer);\r
+                       }); \r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       try\r
+                       {\r
+                               producer_.reset();\r
+                       }\r
+                       catch(...){}\r
+               }\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (*producer_)->receive(hints);}\r
+       virtual safe_ptr<basic_frame>                                                           last_frame() const override                                                                                             {return (*producer_)->last_frame();}\r
+       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame() override                                                                               {return (*producer_)->create_thumbnail_frame();}\r
+       virtual std::wstring                                                                            print() const override                                                                                                  {return (*producer_)->print();}\r
+       virtual boost::property_tree::wptree                                            info() const override                                                                                                   {return (*producer_)->info();}\r
+       virtual boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                  {return (*producer_)->call(str);}\r
+       virtual safe_ptr<frame_producer>                                                        get_following_producer() const override                                                                 {return (*producer_)->get_following_producer();}\r
+       virtual void                                                                                            set_leading_producer(const safe_ptr<frame_producer>& producer) override {(*producer_)->set_leading_producer(producer);}\r
+       virtual uint32_t                                                                                        nb_frames() const override                                                                                              {return (*producer_)->nb_frames();}\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer> producer)\r
+{\r
+       return make_safe<destroy_producer_proxy>(std::move(producer));\r
+}\r
+\r
+class print_producer_proxy : public frame_producer\r
+{      \r
+       std::shared_ptr<frame_producer> producer_;\r
+public:\r
+       print_producer_proxy(safe_ptr<frame_producer>&& producer) \r
+               : producer_(std::move(producer))\r
+       {\r
+               CASPAR_LOG(info) << producer_->print() << L" Initialized.";\r
+       }\r
+\r
+       ~print_producer_proxy()\r
+       {               \r
+               auto str = producer_->print();\r
+               CASPAR_LOG(trace) << str << L" Uninitializing.";\r
+               producer_.reset();\r
+               CASPAR_LOG(info) << str << L" Uninitialized.";\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (producer_)->receive(hints);}\r
+       virtual safe_ptr<basic_frame>                                                           last_frame() const override                                                                                             {return (producer_)->last_frame();}\r
+       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame() override                                                                               {return (producer_)->create_thumbnail_frame();}\r
+       virtual std::wstring                                                                            print() const override                                                                                                  {return (producer_)->print();}\r
+       virtual boost::property_tree::wptree                                            info() const override                                                                                                   {return (producer_)->info();}\r
+       virtual boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                  {return (producer_)->call(str);}\r
+       virtual safe_ptr<frame_producer>                                                        get_following_producer() const override                                                                 {return (producer_)->get_following_producer();}\r
+       virtual void                                                                                            set_leading_producer(const safe_ptr<frame_producer>& producer) override {(producer_)->set_leading_producer(producer);}\r
+       virtual uint32_t                                                                                        nb_frames() const override                                                                                              {return (producer_)->nb_frames();}\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer_print_proxy(safe_ptr<core::frame_producer> producer)\r
+{\r
+       return make_safe<print_producer_proxy>(std::move(producer));\r
+}\r
+\r
+class last_frame_producer : public frame_producer\r
+{\r
+       const std::wstring                      print_;\r
+       const safe_ptr<basic_frame>     frame_;\r
+       const uint32_t                          nb_frames_;\r
+public:\r
+       last_frame_producer(const safe_ptr<frame_producer>& producer) \r
+               : print_(producer->print())\r
+               , frame_(producer->last_frame() != basic_frame::eof() ? producer->last_frame() : basic_frame::empty())\r
+               , nb_frames_(producer->nb_frames())\r
+       {\r
+       }\r
+       \r
+       virtual safe_ptr<basic_frame> receive(int){return frame_;}\r
+       virtual safe_ptr<core::basic_frame> last_frame() const{return frame_;}\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() {return frame_;}\r
+       virtual std::wstring print() const{return L"dummy[" + print_ + L"]";}\r
+       virtual uint32_t nb_frames() const {return nb_frames_;} \r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"last-frame-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+struct empty_frame_producer : public frame_producer\r
+{\r
+       virtual safe_ptr<basic_frame> receive(int){return basic_frame::empty();}\r
+       virtual safe_ptr<basic_frame> last_frame() const{return basic_frame::empty();}\r
+       virtual void set_frame_factory(const safe_ptr<frame_factory>&){}\r
+       virtual uint32_t nb_frames() const {return 0;}\r
+       virtual std::wstring print() const { return L"empty";}\r
+       \r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"empty-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+const safe_ptr<frame_producer>& frame_producer::empty() // nothrow\r
+{\r
+       static safe_ptr<frame_producer> producer = make_safe<empty_frame_producer>();\r
+       return producer;\r
+}\r
+\r
+safe_ptr<basic_frame> frame_producer::create_thumbnail_frame()\r
+{\r
+       return basic_frame::empty();\r
+}\r
+\r
+safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer, int hints)\r
+{      \r
+       auto frame = producer->receive(hints);\r
+       if(frame == basic_frame::eof())\r
+       {\r
+               CASPAR_LOG(info) << producer->print() << " End Of File.";\r
+               auto following = producer->get_following_producer();\r
+               if(following != frame_producer::empty())\r
+               {\r
+                       following->set_leading_producer(producer);\r
+                       producer = std::move(following);\r
+               }\r
+               else\r
+                       producer = make_safe<last_frame_producer>(producer);\r
+\r
+               return receive_and_follow(producer, hints);\r
+       }\r
+       return frame;\r
+}\r
+\r
+void register_producer_factory(const producer_factory_t& factory)\r
+{\r
+       g_factories.push_back(factory);\r
+}\r
+\r
+void register_thumbnail_producer_factory(const producer_factory_t& factory)\r
+{\r
+       g_thumbnail_factories.push_back(factory);\r
+}\r
+\r
+safe_ptr<core::frame_producer> do_create_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::vector<std::wstring>& params, const std::vector<const producer_factory_t>& factories, bool throw_on_fail = false)\r
+{\r
+       if(params.empty())\r
+               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("params") << arg_value_info(""));\r
+       \r
+       auto producer = frame_producer::empty();\r
+       std::any_of(factories.begin(), factories.end(), [&](const producer_factory_t& factory) -> bool\r
+               {\r
+                       try\r
+                       {\r
+                               producer = factory(my_frame_factory, params);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               if (throw_on_fail)\r
+                                       throw;\r
+                               else\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+                       return producer != frame_producer::empty();\r
+               });\r
+\r
+       if(producer == frame_producer::empty())\r
+               producer = create_color_producer(my_frame_factory, params);\r
+       \r
+       if(producer == frame_producer::empty())\r
+               producer = create_playlist_producer(my_frame_factory, params);\r
+       \r
+       return producer;\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::vector<std::wstring>& params)\r
+{      \r
+       auto producer = do_create_producer(my_frame_factory, params, g_factories);\r
+       auto key_producer = frame_producer::empty();\r
+       \r
+       try // to find a key file.\r
+       {\r
+               auto params_copy = params;\r
+               if(params_copy.size() > 0)\r
+               {\r
+                       params_copy[0] += L"_A";\r
+                       key_producer = do_create_producer(my_frame_factory, params_copy, g_factories);                  \r
+                       if(key_producer == frame_producer::empty())\r
+                       {\r
+                               params_copy[0] += L"LPHA";\r
+                               key_producer = do_create_producer(my_frame_factory, params_copy, g_factories);  \r
+                       }\r
+               }\r
+       }\r
+       catch(...){}\r
+\r
+       if(producer != frame_producer::empty() && key_producer != frame_producer::empty())\r
+               return create_separated_producer(producer, key_producer);\r
+       \r
+       if(producer == frame_producer::empty())\r
+       {\r
+               std::wstring str;\r
+               BOOST_FOREACH(auto& param, params)\r
+                       str += param + L" ";\r
+               BOOST_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax.") << arg_value_info(narrow(str)));\r
+       }\r
+\r
+       return producer;\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::wstring& media_file)\r
+{\r
+       std::vector<std::wstring> params;\r
+       params.push_back(media_file);\r
+\r
+       auto producer = do_create_producer(my_frame_factory, params, g_thumbnail_factories, true);\r
+       auto key_producer = frame_producer::empty();\r
+       \r
+       try // to find a key file.\r
+       {\r
+               auto params_copy = params;\r
+               if (params_copy.size() > 0)\r
+               {\r
+                       params_copy[0] += L"_A";\r
+                       key_producer = do_create_producer(my_frame_factory, params_copy, g_thumbnail_factories, true);\r
+                       if (key_producer == frame_producer::empty())\r
+                       {\r
+                               params_copy[0] += L"LPHA";\r
+                               key_producer = do_create_producer(my_frame_factory, params_copy, g_thumbnail_factories, true);\r
+                       }\r
+               }\r
+       }\r
+       catch(...){}\r
+\r
+       if (producer != frame_producer::empty() && key_producer != frame_producer::empty())\r
+               return create_separated_thumbnail_producer(producer, key_producer);\r
+       \r
+       return producer;\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& factory, const std::wstring& params)\r
+{\r
+       std::wstringstream iss(params);\r
+       std::vector<std::wstring> tokens;\r
+       typedef std::istream_iterator<std::wstring, wchar_t, std::char_traits<wchar_t> > iterator;\r
+       std::copy(iterator(iss),  iterator(), std::back_inserter(tokens));\r
+       return create_producer(factory, tokens);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/frame_producer.h b/core/producer/frame_producer.h
new file mode 100644 (file)
index 0000000..a29e78d
--- /dev/null
@@ -0,0 +1,91 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <algorithm>\r
+#include <functional>\r
+#include <string>\r
+#include <vector>\r
+#include <stdint.h>\r
+#include <numeric>\r
+\r
+#include <boost/thread/future.hpp>\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+\r
+namespace caspar { \r
+       \r
+class executor;\r
+       \r
+namespace core {\r
+\r
+class basic_frame;\r
+struct frame_factory;\r
+\r
+struct frame_producer : boost::noncopyable\r
+{\r
+public:\r
+       enum hints\r
+       {\r
+               NO_HINT = 0,\r
+               ALPHA_HINT = 1,\r
+               DEINTERLACE_HINT\r
+       };\r
+\r
+       virtual ~frame_producer(){}     \r
+\r
+       virtual std::wstring print() const = 0; // nothrow\r
+       virtual boost::property_tree::wptree info() const = 0;\r
+\r
+       virtual boost::unique_future<std::wstring> call(const std::wstring&) \r
+       {\r
+               BOOST_THROW_EXCEPTION(not_supported());\r
+       }\r
+\r
+       virtual safe_ptr<frame_producer> get_following_producer() const {return frame_producer::empty();}  // nothrow\r
+       virtual void set_leading_producer(const safe_ptr<frame_producer>&) {}  // nothrow\r
+               \r
+       virtual uint32_t nb_frames() const {return std::numeric_limits<uint32_t>::max();}\r
+       \r
+       virtual safe_ptr<basic_frame> receive(int hints) = 0;\r
+       virtual safe_ptr<core::basic_frame> last_frame() const = 0;\r
+       virtual safe_ptr<basic_frame> create_thumbnail_frame();\r
+\r
+       static const safe_ptr<frame_producer>& empty(); // nothrow\r
+};\r
+\r
+safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer, int hints);\r
+\r
+typedef std::function<safe_ptr<core::frame_producer>(const safe_ptr<frame_factory>&, const std::vector<std::wstring>&)> producer_factory_t;\r
+void register_producer_factory(const producer_factory_t& factory); // Not thread-safe.\r
+void register_thumbnail_producer_factory(const producer_factory_t& factory); // Not thread-safe.\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>&, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>&, const std::wstring& params);\r
+safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer> producer);\r
+safe_ptr<core::frame_producer> create_producer_print_proxy(safe_ptr<core::frame_producer> producer);\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<frame_factory>& factory, const std::wstring& media_file);\r
+\r
+}}\r
diff --git a/core/producer/layer.cpp b/core/producer/layer.cpp
new file mode 100644 (file)
index 0000000..0a0ff51
--- /dev/null
@@ -0,0 +1,192 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "layer.h"\r
+\r
+#include "frame_producer.h"\r
+#include "frame/basic_frame.h"\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+struct layer::implementation\r
+{                              \r
+       safe_ptr<frame_producer>        foreground_;\r
+       safe_ptr<frame_producer>        background_;\r
+       int64_t                                         frame_number_;\r
+       int32_t                                         auto_play_delta_;\r
+       bool                                            is_paused_;\r
+\r
+public:\r
+       implementation() \r
+               : foreground_(frame_producer::empty())\r
+               , background_(frame_producer::empty())\r
+               , frame_number_(0)\r
+               , auto_play_delta_(-1)\r
+               , is_paused_(false)\r
+       {\r
+       }\r
+       \r
+       void pause()\r
+       {\r
+               is_paused_ = true;\r
+       }\r
+\r
+       void resume()\r
+       {\r
+               is_paused_ = false;\r
+       }\r
+\r
+       void load(const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta)\r
+       {               \r
+               background_              = producer;\r
+               auto_play_delta_ = auto_play_delta;\r
+\r
+               if(auto_play_delta_ > -1 && foreground_ == frame_producer::empty())\r
+                       play();\r
+\r
+               if(preview) // Play the first frame and pause.\r
+               {                       \r
+                       play();\r
+                       receive(frame_producer::NO_HINT);\r
+                       pause();\r
+               }\r
+       }\r
+       \r
+       void play()\r
+       {                       \r
+               if(background_ != frame_producer::empty())\r
+               {\r
+                       background_->set_leading_producer(foreground_);\r
+                       \r
+                       foreground_                     = background_;\r
+                       background_                     = frame_producer::empty();\r
+                       frame_number_           = 0;\r
+                       auto_play_delta_        = -1;   \r
+               }\r
+\r
+               is_paused_                      = false;\r
+       }\r
+       \r
+       void stop()\r
+       {\r
+               foreground_                     = frame_producer::empty();\r
+               background_                     = background_;\r
+               frame_number_           = 0;\r
+               auto_play_delta_        = -1;\r
+\r
+               is_paused_                      = true;\r
+       }\r
+               \r
+       safe_ptr<basic_frame> receive(int hints)\r
+       {               \r
+               try\r
+               {\r
+                       if(is_paused_)\r
+                       {\r
+                               if(foreground_->last_frame() == basic_frame::empty())\r
+                                       foreground_->receive(frame_producer::NO_HINT);\r
+\r
+                               return disable_audio(foreground_->last_frame());\r
+                       }\r
+\r
+                       auto frame = receive_and_follow(foreground_, hints);\r
+                       if(frame == core::basic_frame::late())\r
+                               return foreground_->last_frame();\r
+\r
+                       auto frames_left = static_cast<int64_t>(foreground_->nb_frames()) - static_cast<int64_t>(++frame_number_) - static_cast<int64_t>(auto_play_delta_);\r
+                       if(auto_play_delta_ > -1 && frames_left < 1)\r
+                       {\r
+                               play();\r
+                               return receive(hints);\r
+                       }\r
+                               \r
+                       return frame;\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       stop();\r
+                       return core::basic_frame::empty();\r
+               }\r
+       }\r
+\r
+       boost::unique_future<std::wstring> call(bool foreground, const std::wstring& param)\r
+       {\r
+               return (foreground ? foreground_ : background_)->call(param);\r
+       }\r
+\r
+       bool empty() const\r
+       {\r
+               return background_ == core::frame_producer::empty() && foreground_ == core::frame_producer::empty();\r
+       }\r
+\r
+       boost::property_tree::wptree info() const\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"status",             is_paused_ ? L"paused" : (foreground_ == frame_producer::empty() ? L"stopped" : L"playing"));\r
+               info.add(L"auto_delta", auto_play_delta_);\r
+               info.add(L"frame-number", frame_number_);\r
+\r
+               auto nb_frames = foreground_->nb_frames();\r
+\r
+               info.add(L"nb_frames",   nb_frames == std::numeric_limits<int64_t>::max() ? -1 : nb_frames);\r
+               info.add(L"frames-left", nb_frames == std::numeric_limits<int64_t>::max() ? -1 : (foreground_->nb_frames() - frame_number_ - auto_play_delta_));\r
+               info.add_child(L"foreground.producer", foreground_->info());\r
+               info.add_child(L"background.producer", background_->info());\r
+               return info;\r
+       }\r
+};\r
+\r
+layer::layer() : impl_(new implementation()){}\r
+layer::layer(layer&& other) : impl_(std::move(other.impl_)){}\r
+layer& layer::operator=(layer&& other)\r
+{\r
+       impl_ = std::move(other.impl_);\r
+       return *this;\r
+}\r
+layer::layer(const layer& other) : impl_(new implementation(*other.impl_)){}\r
+layer& layer::operator=(const layer& other)\r
+{\r
+       layer temp(other);\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+void layer::swap(layer& other)\r
+{      \r
+       impl_.swap(other.impl_);\r
+}\r
+void layer::load(const safe_ptr<frame_producer>& frame_producer, bool preview, int auto_play_delta){return impl_->load(frame_producer, preview, auto_play_delta);}     \r
+void layer::play(){impl_->play();}\r
+void layer::pause(){impl_->pause();}\r
+void layer::stop(){impl_->stop();}\r
+bool layer::is_paused() const{return impl_->is_paused_;}\r
+int64_t layer::frame_number() const{return impl_->frame_number_;}\r
+safe_ptr<basic_frame> layer::receive(int hints) {return impl_->receive(hints);}\r
+safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
+safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
+bool layer::empty() const {return impl_->empty();}\r
+boost::unique_future<std::wstring> layer::call(bool foreground, const std::wstring& param){return impl_->call(foreground, param);}\r
+boost::property_tree::wptree layer::info() const{return impl_->info();}\r
+}}
\ No newline at end of file
diff --git a/core/producer/layer.h b/core/producer/layer.h
new file mode 100644 (file)
index 0000000..38ccd43
--- /dev/null
@@ -0,0 +1,70 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct frame_producer;\r
+class basic_frame;\r
+\r
+class layer : boost::noncopyable\r
+{\r
+public:\r
+       layer(); // nothrow\r
+       layer(layer&& other); // nothrow\r
+       layer& operator=(layer&& other); // nothrow\r
+       layer(const layer&);\r
+       layer& operator=(const layer&);\r
+\r
+       void swap(layer& other); // nothrow \r
+               \r
+       void load(const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta); // nothrow\r
+       void play(); // nothrow\r
+       void pause(); // nothrow\r
+       void stop(); // nothrow\r
+       boost::unique_future<std::wstring> call(bool foreground, const std::wstring& param);\r
+\r
+       bool is_paused() const;\r
+       int64_t frame_number() const;\r
+       \r
+       bool empty() const;\r
+\r
+       safe_ptr<frame_producer> foreground() const; // nothrow\r
+       safe_ptr<frame_producer> background() const; // nothrow\r
+\r
+       safe_ptr<basic_frame> receive(int hints); // nothrow\r
+\r
+       boost::property_tree::wptree info() const;\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/playlist/playlist_producer.cpp b/core/producer/playlist/playlist_producer.cpp
new file mode 100644 (file)
index 0000000..2068e2a
--- /dev/null
@@ -0,0 +1,222 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "playlist_producer.h"\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/producer/frame/basic_frame.h>\r
+\r
+#include <boost/regex.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <deque>\r
+\r
+namespace caspar { namespace core {    \r
+\r
+struct playlist_producer : public frame_producer\r
+{                              \r
+       safe_ptr<frame_factory>                         factory_;\r
+       safe_ptr<basic_frame>                           last_frame_;\r
+       safe_ptr<frame_producer>                        current_;\r
+       bool                                                            loop_;\r
+\r
+       std::deque<safe_ptr<frame_producer>> producers_;\r
+\r
+       playlist_producer(const safe_ptr<frame_factory>& factory, bool loop) \r
+               : factory_(factory)\r
+               , last_frame_(basic_frame::empty())\r
+               , current_(frame_producer::empty())\r
+               , loop_(loop)\r
+       {\r
+       }\r
+\r
+       // frame_producer\r
+       \r
+       virtual safe_ptr<basic_frame> receive(int hints) override\r
+       {\r
+               if(current_ == frame_producer::empty() && !producers_.empty())\r
+                       next();\r
+\r
+               auto frame = current_->receive(hints);\r
+               if(frame == basic_frame::eof())\r
+               {\r
+                       current_ = frame_producer::empty();\r
+                       return receive(hints);\r
+               }\r
+\r
+               return last_frame_ = frame;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return disable_audio(last_frame_);\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"playlist[" + current_->print() + L"]";\r
+       }       \r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"playlist-producer");\r
+               return info;\r
+       }\r
+\r
+       virtual uint32_t nb_frames() const  override\r
+       {\r
+               return std::numeric_limits<uint32_t>::max();\r
+       }\r
+       \r
+       virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
+       {\r
+               boost::promise<std::wstring> promise;\r
+               promise.set_value(do_call(param));\r
+               return promise.get_future();\r
+       }       \r
+\r
+       // playlist_producer\r
+\r
+       std::wstring do_call(const std::wstring& param)\r
+       {               \r
+               static const boost::wregex push_front_exp       (L"PUSH_FRONT (?<PARAM>.+)");           \r
+               static const boost::wregex push_back_exp        (L"(PUSH_BACK|PUSH) (?<PARAM>.+)");\r
+               static const boost::wregex pop_front_exp        (L"POP_FRONT");         \r
+               static const boost::wregex pop_back_exp         (L"(POP_BACK|POP)");\r
+               static const boost::wregex clear_exp            (L"CLEAR");\r
+               static const boost::wregex next_exp                     (L"NEXT");\r
+               static const boost::wregex insert_exp           (L"INSERT (?<POS>\\d+) (?<PARAM>.+)");  \r
+               static const boost::wregex remove_exp           (L"REMOVE (?<POS>\\d+) (?<PARAM>.+)");  \r
+               static const boost::wregex list_exp                     (L"LIST");                      \r
+               static const boost::wregex loop_exp                     (L"LOOP\\s*(?<VALUE>\\d?)");\r
+               \r
+               boost::wsmatch what;\r
+\r
+               if(boost::regex_match(param, what, push_front_exp))\r
+                       return push_front(what["PARAM"].str()); \r
+               else if(boost::regex_match(param, what, push_back_exp))\r
+                       return push_back(what["PARAM"].str()); \r
+               if(boost::regex_match(param, what, pop_front_exp))\r
+                       return pop_front(); \r
+               else if(boost::regex_match(param, what, pop_back_exp))\r
+                       return pop_back(); \r
+               else if(boost::regex_match(param, what, clear_exp))\r
+                       return clear();\r
+               else if(boost::regex_match(param, what, next_exp))\r
+                       return next(); \r
+               else if(boost::regex_match(param, what, insert_exp))\r
+                       return insert(boost::lexical_cast<size_t>(what["POS"].str()), what["PARAM"].str());\r
+               else if(boost::regex_match(param, what, remove_exp))\r
+                       return erase(boost::lexical_cast<size_t>(what["POS"].str()));\r
+               else if(boost::regex_match(param, what, list_exp))\r
+                       return list();\r
+               else if(boost::regex_match(param, what, loop_exp))\r
+               {\r
+                       if(!what["VALUE"].str().empty())\r
+                               loop_ = boost::lexical_cast<bool>(what["VALUE"].str());\r
+                       return boost::lexical_cast<std::wstring>(loop_);\r
+               }\r
+\r
+               BOOST_THROW_EXCEPTION(invalid_argument());\r
+       }\r
+       \r
+       std::wstring push_front(const std::wstring& str)\r
+       {\r
+               producers_.push_front(create_producer(factory_, str)); \r
+               return L"";\r
+       }\r
+\r
+       std::wstring  push_back(const std::wstring& str)\r
+       {\r
+               producers_.push_back(create_producer(factory_, str)); \r
+               return L"";\r
+       }\r
+\r
+       std::wstring pop_front()\r
+       {\r
+               producers_.pop_front();\r
+               return L"";\r
+       }\r
+\r
+       std::wstring pop_back()\r
+       {\r
+               producers_.pop_back();\r
+               return L"";\r
+       }\r
+       \r
+       std::wstring clear()\r
+       {\r
+               producers_.clear();\r
+               return L"";\r
+       }\r
+\r
+       std::wstring next()\r
+       {\r
+               if(!producers_.empty())\r
+               {\r
+                       current_ = producers_.front();\r
+                       producers_.pop_front();\r
+                       //if(loop_)\r
+                       //      producers_.push_back(current_);\r
+               }\r
+               return L"";\r
+       }\r
+       \r
+       std::wstring  insert(size_t pos, const std::wstring& str)\r
+       {\r
+               if(pos >= producers_.size())\r
+                       BOOST_THROW_EXCEPTION(out_of_range());\r
+               producers_.insert(std::begin(producers_) + pos, create_producer(factory_, str));\r
+               return L"";\r
+       }\r
+\r
+       std::wstring  erase(size_t pos)\r
+       {\r
+               if(pos >= producers_.size())\r
+                       BOOST_THROW_EXCEPTION(out_of_range());\r
+               producers_.erase(std::begin(producers_) + pos);\r
+               return L"";\r
+       }\r
+\r
+       std::wstring list() const\r
+       {\r
+               std::wstring result = L"<playlist>\n";\r
+               BOOST_FOREACH(auto& producer, producers_)               \r
+                       result += L"\t<producer>" + producer->print() + L"</producer>\n";\r
+               return result + L"</playlist>";\r
+       }\r
+};\r
+\r
+safe_ptr<frame_producer> create_playlist_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       if(boost::range::find(params, L"[PLAYLIST]") == params.end())\r
+               return core::frame_producer::empty();\r
+\r
+       bool loop = boost::range::find(params, L"LOOP") != params.end();\r
+\r
+       return make_safe<playlist_producer>(frame_factory, loop);\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/producer/playlist/playlist_producer.h b/core/producer/playlist/playlist_producer.h
new file mode 100644 (file)
index 0000000..23c130c
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <memory>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+safe_ptr<frame_producer> create_playlist_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/separated/separated_producer.cpp b/core/producer/separated/separated_producer.cpp
new file mode 100644 (file)
index 0000000..9ef26c6
--- /dev/null
@@ -0,0 +1,133 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "separated_producer.h"\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+\r
+#include <tbb/parallel_invoke.h>\r
+\r
+namespace caspar { namespace core {    \r
+\r
+struct separated_producer : public frame_producer\r
+{              \r
+       safe_ptr<frame_producer>        fill_producer_;\r
+       safe_ptr<frame_producer>        key_producer_;\r
+       safe_ptr<basic_frame>           fill_;\r
+       safe_ptr<basic_frame>           key_;\r
+       safe_ptr<basic_frame>           last_frame_;\r
+               \r
+       explicit separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key) \r
+               : fill_producer_(fill)\r
+               , key_producer_(key)\r
+               , fill_(core::basic_frame::late())\r
+               , key_(core::basic_frame::late())\r
+               , last_frame_(core::basic_frame::empty())\r
+       {\r
+       }\r
+\r
+       // frame_producer\r
+       \r
+       virtual safe_ptr<basic_frame> receive(int hints) override\r
+       {\r
+               tbb::parallel_invoke(\r
+               [&]\r
+               {\r
+                       if(fill_ == core::basic_frame::late())\r
+                               fill_ = receive_and_follow(fill_producer_, hints);\r
+               },\r
+               [&]\r
+               {\r
+                       if(key_ == core::basic_frame::late())\r
+                               key_ = receive_and_follow(key_producer_, hints | ALPHA_HINT);\r
+               });\r
+\r
+               if(fill_ == basic_frame::eof() || key_ == basic_frame::eof())\r
+                       return basic_frame::eof();\r
+\r
+               if(fill_ == core::basic_frame::late() || key_ == core::basic_frame::late()) // One of the producers is lagging, keep them in sync.\r
+                       return core::basic_frame::late();\r
+               \r
+               auto frame = basic_frame::fill_and_key(fill_, key_);\r
+\r
+               fill_ = basic_frame::late();\r
+               key_  = basic_frame::late();\r
+\r
+               return last_frame_ = frame;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return disable_audio(last_frame_);\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame> create_thumbnail_frame() override\r
+       {\r
+               auto fill_frame = fill_producer_->create_thumbnail_frame();\r
+               auto key_frame = key_producer_->create_thumbnail_frame();\r
+\r
+               if (fill_frame == basic_frame::empty() || key_frame == basic_frame::empty())\r
+                       return basic_frame::empty();\r
+\r
+               if (fill_frame == basic_frame::eof() || key_frame == basic_frame::eof())\r
+                       return basic_frame::eof();\r
+\r
+               if (fill_frame == basic_frame::late() || key_frame == basic_frame::late())\r
+                       return basic_frame::late();\r
+\r
+               return basic_frame::fill_and_key(fill_frame, key_frame);\r
+       }\r
+\r
+       virtual uint32_t nb_frames() const override\r
+       {\r
+               return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames());\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"separated[fill:" + fill_producer_->print() + L"|key[" + key_producer_->print() + L"]]";\r
+       }       \r
+\r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"separated-producer");\r
+               info.add_child(L"fill.producer",        fill_producer_->info());\r
+               info.add_child(L"key.producer", key_producer_->info());\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
+{\r
+       return create_producer_print_proxy(\r
+                       make_safe<separated_producer>(fill, key));\r
+}\r
+\r
+safe_ptr<frame_producer> create_separated_thumbnail_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
+{\r
+       return make_safe<separated_producer>(fill, key);\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/producer/separated/separated_producer.h b/core/producer/separated/separated_producer.h
new file mode 100644 (file)
index 0000000..3937243
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <memory>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key);\r
+safe_ptr<frame_producer> create_separated_thumbnail_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/stage.cpp b/core/producer/stage.cpp
new file mode 100644 (file)
index 0000000..3422cf4
--- /dev/null
@@ -0,0 +1,393 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "stage.h"\r
+\r
+#include "layer.h"\r
+\r
+#include "frame/basic_frame.h"\r
+#include "frame/frame_factory.h"\r
+\r
+#include <common/concurrency/executor.h>\r
+\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/timer.hpp>\r
+\r
+#include <tbb/parallel_for_each.h>\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <map>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+template<typename T>\r
+class tweened_transform\r
+{\r
+       T source_;\r
+       T dest_;\r
+       int duration_;\r
+       int time_;\r
+       tweener_t tweener_;\r
+public:        \r
+       tweened_transform()\r
+               : duration_(0)\r
+               , time_(0)\r
+               , tweener_(get_tweener(L"linear")){}\r
+       tweened_transform(const T& source, const T& dest, int duration, const std::wstring& tween = L"linear")\r
+               : source_(source)\r
+               , dest_(dest)\r
+               , duration_(duration)\r
+               , time_(0)\r
+               , tweener_(get_tweener(tween)){}\r
+       \r
+       const T& source() const\r
+       {\r
+               return source_;\r
+       }\r
+       \r
+       const T& dest() const\r
+       {\r
+               return dest_;\r
+       }\r
+\r
+       T fetch()\r
+       {\r
+               return time_ == duration_ ? dest_ : tween(static_cast<double>(time_), source_, dest_, static_cast<double>(duration_), tweener_);\r
+       }\r
+\r
+       T fetch_and_tick(int num)\r
+       {                                               \r
+               time_ = std::min(time_+num, duration_);\r
+               return fetch();\r
+       }\r
+};\r
+\r
+struct stage::implementation : public std::enable_shared_from_this<implementation>\r
+                                                        , boost::noncopyable\r
+{              \r
+       safe_ptr<diagnostics::graph>                                                                                             graph_;\r
+       safe_ptr<stage::target_t>                                                                                                        target_;\r
+       video_format_desc                                                                                                                        format_desc_;\r
+                                                                                                                                                                \r
+       boost::timer                                                                                                                             produce_timer_;\r
+       boost::timer                                                                                                                             tick_timer_;\r
+                                                                                                                                                                \r
+       std::map<int, layer>                                                                                                             layers_;       \r
+       tbb::concurrent_unordered_map<int, tweened_transform<core::frame_transform>> transforms_;       \r
+\r
+       executor                                                executor_;\r
+public:\r
+       implementation(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<stage::target_t>& target, const video_format_desc& format_desc)  \r
+               : graph_(graph)\r
+               , format_desc_(format_desc)\r
+               , target_(target)\r
+               , executor_(L"stage")\r
+       {\r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f, 0.8));      \r
+               graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
+       }\r
+\r
+       void spawn_token()\r
+       {\r
+               std::weak_ptr<implementation> self = shared_from_this();\r
+               executor_.begin_invoke([=]{tick(self);});\r
+       }\r
+                                                       \r
+       void tick(const std::weak_ptr<implementation>& self)\r
+       {               \r
+               try\r
+               {\r
+                       produce_timer_.restart();\r
+\r
+                       std::map<int, safe_ptr<basic_frame>> frames;\r
+               \r
+                       BOOST_FOREACH(auto& layer, layers_)                     \r
+                               frames[layer.first] = basic_frame::empty();     \r
+\r
+                       tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, layer>::value_type& layer) \r
+                       {\r
+                               auto transform = transforms_[layer.first].fetch_and_tick(1);\r
+\r
+                               int hints = frame_producer::NO_HINT;\r
+                               if(format_desc_.field_mode != field_mode::progressive)\r
+                               {\r
+                                       hints |= std::abs(transform.fill_scale[1]  - 1.0) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;\r
+                                       hints |= std::abs(transform.fill_translation[1]) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;\r
+                               }\r
+\r
+                               if(transform.is_key)\r
+                                       hints |= frame_producer::ALPHA_HINT;\r
+\r
+                               auto frame = layer.second.receive(hints);       \r
+                               \r
+                               auto frame1 = make_safe<core::basic_frame>(frame);\r
+                               frame1->get_frame_transform() = transform;\r
+\r
+                               if(format_desc_.field_mode != core::field_mode::progressive)\r
+                               {                               \r
+                                       auto frame2 = make_safe<core::basic_frame>(frame);\r
+                                       frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);\r
+                                       frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);\r
+                               }\r
+\r
+                               frames[layer.first] = frame1;\r
+                       });\r
+                       \r
+                       graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);\r
+                       \r
+                       std::shared_ptr<void> ticket(nullptr, [self](void*)\r
+                       {\r
+                               auto self2 = self.lock();\r
+                               if(self2)                               \r
+                                       self2->executor_.begin_invoke([=]{tick(self);});                                \r
+                       });\r
+\r
+                       target_->send(std::make_pair(frames, ticket));\r
+\r
+                       graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
+                       tick_timer_.restart();\r
+               }\r
+               catch(...)\r
+               {\r
+                       layers_.clear();\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }               \r
+       }\r
+               \r
+       void set_transform(int index, const frame_transform& transform, unsigned int mix_duration, const std::wstring& tween)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       auto src = transforms_[index].fetch();\r
+                       auto dst = transform;\r
+                       transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
+               }, high_priority);\r
+       }\r
+                                       \r
+       void apply_transforms(const std::vector<std::tuple<int, stage::transform_func_t, unsigned int, std::wstring>>& transforms)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       BOOST_FOREACH(auto& transform, transforms)\r
+                       {\r
+                               auto& tween = transforms_[std::get<0>(transform)];\r
+                               auto src = tween.fetch();\r
+                               auto dst = std::get<1>(transform)(tween.dest());\r
+                               transforms_[std::get<0>(transform)] = tweened_transform<frame_transform>(src, dst, std::get<2>(transform), std::get<3>(transform));\r
+                       }\r
+               }, high_priority);\r
+       }\r
+                                               \r
+       void apply_transform(int index, const stage::transform_func_t& transform, unsigned int mix_duration, const std::wstring& tween)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       auto src = transforms_[index].fetch();\r
+                       auto dst = transform(src);\r
+                       transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
+               }, high_priority);\r
+       }\r
+\r
+       void clear_transforms(int index)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       transforms_[index] = tweened_transform<core::frame_transform>();\r
+               }, high_priority);\r
+       }\r
+\r
+       void clear_transforms()\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       transforms_.clear();\r
+               }, high_priority);\r
+       }\r
+               \r
+       void load(int index, const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_[index].load(producer, preview, auto_play_delta);\r
+               }, high_priority);\r
+       }\r
+\r
+       void pause(int index)\r
+       {               \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_[index].pause();\r
+               }, high_priority);\r
+       }\r
+\r
+       void play(int index)\r
+       {               \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_[index].play();\r
+               }, high_priority);\r
+       }\r
+\r
+       void stop(int index)\r
+       {               \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_[index].stop();\r
+               }, high_priority);\r
+       }\r
+\r
+       void clear(int index)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_.erase(index);\r
+               }, high_priority);\r
+       }\r
+               \r
+       void clear()\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       layers_.clear();\r
+               }, high_priority);\r
+       }       \r
+       \r
+       boost::unique_future<std::wstring> call(int index, bool foreground, const std::wstring& param)\r
+       {\r
+               return std::move(*executor_.invoke([=]\r
+               {\r
+                       return std::make_shared<boost::unique_future<std::wstring>>(std::move(layers_[index].call(foreground, param)));\r
+               }, high_priority));\r
+       }\r
+       \r
+       void swap_layers(const safe_ptr<stage>& other)\r
+       {\r
+               if(other->impl_.get() == this)\r
+                       return;\r
+               \r
+               auto func = [=]\r
+               {\r
+                       std::swap(layers_, other->impl_->layers_);\r
+               };              \r
+               executor_.begin_invoke([=]\r
+               {\r
+                       other->impl_->executor_.invoke(func, high_priority);\r
+               }, high_priority);\r
+       }\r
+\r
+       void swap_layer(int index, size_t other_index)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       std::swap(layers_[index], layers_[other_index]);\r
+               }, high_priority);\r
+       }\r
+\r
+       void swap_layer(int index, size_t other_index, const safe_ptr<stage>& other)\r
+       {\r
+               if(other->impl_.get() == this)\r
+                       swap_layer(index, other_index);\r
+               else\r
+               {\r
+                       auto func = [=]\r
+                       {\r
+                               std::swap(layers_[index], other->impl_->layers_[other_index]);\r
+                       };              \r
+                       executor_.begin_invoke([=]\r
+                       {\r
+                               other->impl_->executor_.invoke(func, high_priority);\r
+                       }, high_priority);\r
+               }\r
+       }\r
+               \r
+       boost::unique_future<safe_ptr<frame_producer>> foreground(int index)\r
+       {\r
+               return executor_.begin_invoke([=]\r
+               {\r
+                       return layers_[index].foreground();\r
+               }, high_priority);\r
+       }\r
+       \r
+       boost::unique_future<safe_ptr<frame_producer>> background(int index)\r
+       {\r
+               return executor_.begin_invoke([=]\r
+               {\r
+                       return layers_[index].background();\r
+               }, high_priority);\r
+       }\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc)\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       format_desc_ = format_desc;\r
+               }, high_priority);\r
+       }\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info()\r
+       {\r
+               return std::move(executor_.begin_invoke([this]() -> boost::property_tree::wptree\r
+               {\r
+                       boost::property_tree::wptree info;\r
+                       BOOST_FOREACH(auto& layer, layers_)                     \r
+                               info.add_child(L"layers.layer", layer.second.info())\r
+                                       .add(L"index", layer.first);    \r
+                       return info;\r
+               }, high_priority));\r
+       }\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info(int index)\r
+       {\r
+               return std::move(executor_.begin_invoke([=]() -> boost::property_tree::wptree\r
+               {\r
+                       return layers_[index].info();\r
+               }, high_priority));\r
+       }\r
+};\r
+\r
+stage::stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc) : impl_(new implementation(graph, target, format_desc)){}\r
+void stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms){impl_->apply_transforms(transforms);}\r
+void stage::apply_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);}\r
+void stage::clear_transforms(int index){impl_->clear_transforms(index);}\r
+void stage::clear_transforms(){impl_->clear_transforms();}\r
+void stage::spawn_token(){impl_->spawn_token();}\r
+void stage::load(int index, const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta){impl_->load(index, producer, preview, auto_play_delta);}\r
+void stage::pause(int index){impl_->pause(index);}\r
+void stage::play(int index){impl_->play(index);}\r
+void stage::stop(int index){impl_->stop(index);}\r
+void stage::clear(int index){impl_->clear(index);}\r
+void stage::clear(){impl_->clear();}\r
+void stage::swap_layers(const safe_ptr<stage>& other){impl_->swap_layers(other);}\r
+void stage::swap_layer(int index, size_t other_index){impl_->swap_layer(index, other_index);}\r
+void stage::swap_layer(int index, size_t other_index, const safe_ptr<stage>& other){impl_->swap_layer(index, other_index, other);}\r
+boost::unique_future<safe_ptr<frame_producer>> stage::foreground(int index) {return impl_->foreground(index);}\r
+boost::unique_future<safe_ptr<frame_producer>> stage::background(int index) {return impl_->background(index);}\r
+boost::unique_future<std::wstring> stage::call(int index, bool foreground, const std::wstring& param){return impl_->call(index, foreground, param);}\r
+void stage::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
+boost::unique_future<boost::property_tree::wptree> stage::info() const{return impl_->info();}\r
+boost::unique_future<boost::property_tree::wptree> stage::info(int index) const{return impl_->info(index);}\r
+}}
\ No newline at end of file
diff --git a/core/producer/stage.h b/core/producer/stage.h
new file mode 100644 (file)
index 0000000..e7178ca
--- /dev/null
@@ -0,0 +1,83 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "frame_producer.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/concurrency/target.h>\r
+#include <common/diagnostics/graph.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <functional>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct video_format_desc;\r
+struct frame_transform;\r
+\r
+class stage : boost::noncopyable\r
+{\r
+public:\r
+       typedef std::function<struct frame_transform(struct frame_transform)>                                                   transform_func_t;\r
+       typedef std::tuple<int, transform_func_t, unsigned int, std::wstring>                                                   transform_tuple_t;\r
+       typedef target<std::pair<std::map<int, safe_ptr<basic_frame>>, std::shared_ptr<void>>> target_t;\r
+\r
+       explicit stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc);\r
+       \r
+       // stage\r
+       \r
+       void apply_transforms(const std::vector<transform_tuple_t>& transforms);\r
+       void apply_transform(int index, const transform_func_t& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void clear_transforms(int index);\r
+       void clear_transforms();\r
+\r
+       void spawn_token();\r
+                       \r
+       void load(int index, const safe_ptr<frame_producer>& producer, bool preview = false, int auto_play_delta = -1);\r
+       void pause(int index);\r
+       void play(int index);\r
+       void stop(int index);\r
+       void clear(int index);\r
+       void clear();   \r
+       void swap_layers(const safe_ptr<stage>& other);\r
+       void swap_layer(int index, size_t other_index);\r
+       void swap_layer(int index, size_t other_index, const safe_ptr<stage>& other);\r
+       \r
+       boost::unique_future<std::wstring>                              call(int index, bool foreground, const std::wstring& param);\r
+       boost::unique_future<safe_ptr<frame_producer>>  foreground(int index);\r
+       boost::unique_future<safe_ptr<frame_producer>>  background(int index);\r
+\r
+       boost::unique_future<boost::property_tree::wptree> info() const;\r
+       boost::unique_future<boost::property_tree::wptree> info(int layer) const;\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc);\r
+\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/transition/transition_producer.cpp b/core/producer/transition/transition_producer.cpp
new file mode 100644 (file)
index 0000000..88f56b9
--- /dev/null
@@ -0,0 +1,198 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "transition_producer.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
+#include <tbb/parallel_invoke.h>\r
+\r
+#include <boost/assign.hpp>\r
+\r
+using namespace boost::assign;\r
+\r
+namespace caspar { namespace core {    \r
+\r
+struct transition_producer : public frame_producer\r
+{      \r
+       const field_mode::type          mode_;\r
+       unsigned int                            current_frame_;\r
+       \r
+       const transition_info           info_;\r
+       \r
+       safe_ptr<frame_producer>        dest_producer_;\r
+       safe_ptr<frame_producer>        source_producer_;\r
+\r
+       safe_ptr<basic_frame>           last_frame_;\r
+               \r
+       explicit transition_producer(const field_mode::type& mode, const safe_ptr<frame_producer>& dest, const transition_info& info) \r
+               : mode_(mode)\r
+               , current_frame_(0)\r
+               , info_(info)\r
+               , dest_producer_(dest)\r
+               , source_producer_(frame_producer::empty())\r
+               , last_frame_(basic_frame::empty()){}\r
+       \r
+       // frame_producer\r
+\r
+       virtual safe_ptr<frame_producer> get_following_producer() const override\r
+       {\r
+               return dest_producer_;\r
+       }\r
+       \r
+       virtual void set_leading_producer(const safe_ptr<frame_producer>& producer) override\r
+       {\r
+               source_producer_ = producer;\r
+       }\r
+\r
+       virtual boost::unique_future<std::wstring> call(const std::wstring& params) override\r
+       {\r
+               return dest_producer_->call(params);\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame> receive(int hints) override\r
+       {\r
+               if(++current_frame_ >= info_.duration)\r
+                       return basic_frame::eof();\r
+               \r
+               auto dest = basic_frame::empty();\r
+               auto source = basic_frame::empty();\r
+\r
+               tbb::parallel_invoke(\r
+               [&]\r
+               {\r
+                       dest = receive_and_follow(dest_producer_, hints);\r
+                       if(dest == core::basic_frame::late())\r
+                               dest = dest_producer_->last_frame();\r
+               },\r
+               [&]\r
+               {\r
+                       source = receive_and_follow(source_producer_, hints);\r
+                       if(source == core::basic_frame::late())\r
+                               source = source_producer_->last_frame();\r
+               });\r
+\r
+               return compose(dest, source);\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return disable_audio(last_frame_);\r
+       }\r
+\r
+       virtual uint32_t nb_frames() const override\r
+       {\r
+               return get_following_producer()->nb_frames();\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"transition[" + source_producer_->print() + L"=>" + dest_producer_->print() + L"]";\r
+       }\r
+       \r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"transition-producer");\r
+               info.add_child(L"source.producer",         source_producer_->info());\r
+               info.add_child(L"destination.producer", dest_producer_->info());\r
+               return info;\r
+       }\r
+\r
+       // transition_producer\r
+                                               \r
+       safe_ptr<basic_frame> compose(const safe_ptr<basic_frame>& dest_frame, const safe_ptr<basic_frame>& src_frame) \r
+       {       \r
+               if(info_.type == transition::cut)               \r
+                       return src_frame;\r
+                                                                               \r
+               const double delta1 = info_.tweener(current_frame_*2-1, 0.0, 1.0, info_.duration*2);\r
+               const double delta2 = info_.tweener(current_frame_*2, 0.0, 1.0, info_.duration*2);  \r
+\r
+               const double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0;             \r
+               \r
+               // For interlaced transitions. Seperate fields into seperate frames which are transitioned accordingly.\r
+               \r
+               auto s_frame1 = make_safe<basic_frame>(src_frame);\r
+               auto s_frame2 = make_safe<basic_frame>(src_frame);\r
+\r
+               s_frame1->get_frame_transform().volume = 0.0;\r
+               s_frame2->get_frame_transform().volume = 1.0-delta2;\r
+\r
+               auto d_frame1 = make_safe<basic_frame>(dest_frame);\r
+               auto d_frame2 = make_safe<basic_frame>(dest_frame);\r
+               \r
+               d_frame1->get_frame_transform().volume = 0.0;\r
+               d_frame2->get_frame_transform().volume = delta2;\r
+\r
+               if(info_.type == transition::mix)\r
+               {\r
+                       d_frame1->get_frame_transform().opacity = delta1;       \r
+                       d_frame1->get_frame_transform().is_mix = true;\r
+                       d_frame2->get_frame_transform().opacity = delta2;\r
+                       d_frame2->get_frame_transform().is_mix = true;\r
+\r
+                       s_frame1->get_frame_transform().opacity = 1.0-delta1;   \r
+                       s_frame1->get_frame_transform().is_mix = true;\r
+                       s_frame2->get_frame_transform().opacity = 1.0-delta2;   \r
+                       s_frame2->get_frame_transform().is_mix = true;\r
+               }\r
+               if(info_.type == transition::slide)\r
+               {\r
+                       d_frame1->get_frame_transform().fill_translation[0] = (-1.0+delta1)*dir;        \r
+                       d_frame2->get_frame_transform().fill_translation[0] = (-1.0+delta2)*dir;                \r
+               }\r
+               else if(info_.type == transition::push)\r
+               {\r
+                       d_frame1->get_frame_transform().fill_translation[0] = (-1.0+delta1)*dir;\r
+                       d_frame2->get_frame_transform().fill_translation[0] = (-1.0+delta2)*dir;\r
+\r
+                       s_frame1->get_frame_transform().fill_translation[0] = (0.0+delta1)*dir; \r
+                       s_frame2->get_frame_transform().fill_translation[0] = (0.0+delta2)*dir;         \r
+               }\r
+               else if(info_.type == transition::wipe)         \r
+               {\r
+                       d_frame1->get_frame_transform().clip_scale[0] = delta1; \r
+                       d_frame2->get_frame_transform().clip_scale[0] = delta2;                 \r
+               }\r
+                               \r
+               const auto s_frame = s_frame1->get_frame_transform() == s_frame2->get_frame_transform() ? s_frame2 : basic_frame::interlace(s_frame1, s_frame2, mode_);\r
+               const auto d_frame = d_frame1->get_frame_transform() == d_frame2->get_frame_transform() ? d_frame2 : basic_frame::interlace(d_frame1, d_frame2, mode_);\r
+               \r
+               last_frame_ = basic_frame::combine(s_frame2, d_frame2);\r
+\r
+               return basic_frame::combine(s_frame, d_frame);\r
+       }\r
+};\r
+\r
+safe_ptr<frame_producer> create_transition_producer(const field_mode::type& mode, const safe_ptr<frame_producer>& destination, const transition_info& info)\r
+{\r
+       return create_producer_print_proxy(\r
+                       make_safe<transition_producer>(mode, destination, info));\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/producer/transition/transition_producer.h b/core/producer/transition/transition_producer.h
new file mode 100644 (file)
index 0000000..b185d10
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+#include "../../video_format.h"\r
+\r
+#include <common/utility/tweener.h>\r
+\r
+#include <string>\r
+#include <memory>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct transition\r
+{\r
+       enum type\r
+       {\r
+\r
+               cut = 1,\r
+               mix,\r
+               push,\r
+               slide,\r
+               wipe\r
+       };\r
+};\r
+\r
+struct transition_direction\r
+{\r
+       enum type\r
+       {\r
+               from_left = 1,\r
+               from_right\r
+       };\r
+};\r
+\r
+struct transition_info\r
+{\r
+       transition_info() \r
+               : type(transition::cut)\r
+               , duration(0)\r
+               , direction(transition_direction::from_left)\r
+               , tweener(get_tweener(L"linear")){}\r
+               \r
+       size_t                                          duration;\r
+       transition_direction::type      direction;\r
+       transition::type                        type;\r
+       tweener_t                                       tweener;\r
+};\r
+\r
+safe_ptr<frame_producer> create_transition_producer(const field_mode::type& mode, const safe_ptr<frame_producer>& destination, const transition_info& info);\r
+\r
+}}
\ No newline at end of file
diff --git a/core/thumbnail_generator.cpp b/core/thumbnail_generator.cpp
new file mode 100644 (file)
index 0000000..d98495f
--- /dev/null
@@ -0,0 +1,376 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "stdafx.h"\r
+\r
+#include "thumbnail_generator.h"\r
+\r
+#include <iostream>\r
+#include <iterator>\r
+#include <set>\r
+\r
+#include <boost/thread.hpp>\r
+#include <boost/range/algorithm/transform.hpp>\r
+#include <boost/algorithm/string/predicate.hpp>\r
+\r
+#include <tbb/atomic.h>\r
+\r
+#include "producer/frame_producer.h"\r
+#include "consumer/frame_consumer.h"\r
+#include "mixer/mixer.h"\r
+#include "video_format.h"\r
+#include "producer/frame/basic_frame.h"\r
+#include "producer/frame/frame_transform.h"\r
+\r
+namespace caspar { namespace core {\r
+\r
+std::wstring get_relative_without_extension(\r
+               const boost::filesystem::wpath& file,\r
+               const boost::filesystem::wpath& relative_to)\r
+{\r
+       auto result = file.stem();\r
+               \r
+       boost::filesystem::wpath current_path = file;\r
+\r
+       while (true)\r
+       {\r
+               current_path = current_path.parent_path();\r
+\r
+               if (boost::filesystem::equivalent(current_path, relative_to))\r
+                       break;\r
+\r
+               if (current_path.empty())\r
+                       throw std::runtime_error("File not relative to folder");\r
+\r
+               result = current_path.filename() + L"/" + result;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+struct thumbnail_output : public mixer::target_t\r
+{\r
+       tbb::atomic<int> sleep_millis;\r
+       std::function<void (const safe_ptr<read_frame>& frame)> on_send;\r
+\r
+       thumbnail_output(int sleep_millis)\r
+       {\r
+               this->sleep_millis = sleep_millis;\r
+       }\r
+\r
+       void send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame_and_ticket)\r
+       {\r
+               int current_sleep = sleep_millis;\r
+\r
+               if (current_sleep > 0)\r
+                       boost::this_thread::sleep(boost::posix_time::milliseconds(current_sleep));\r
+\r
+               on_send(frame_and_ticket.first);\r
+               on_send = nullptr;\r
+       }\r
+};\r
+\r
+struct thumbnail_generator::implementation\r
+{\r
+private:\r
+       boost::filesystem::wpath media_path_;\r
+       boost::filesystem::wpath thumbnails_path_;\r
+       int width_;\r
+       int height_;\r
+       safe_ptr<ogl_device> ogl_;\r
+       safe_ptr<diagnostics::graph> graph_;\r
+       video_format_desc format_desc_;\r
+       safe_ptr<thumbnail_output> output_;\r
+       safe_ptr<mixer> mixer_;\r
+       thumbnail_creator thumbnail_creator_;\r
+       filesystem_monitor::ptr monitor_;\r
+public:\r
+       implementation(\r
+                       filesystem_monitor_factory& monitor_factory,\r
+                       const boost::filesystem::wpath& media_path,\r
+                       const boost::filesystem::wpath& thumbnails_path,\r
+                       int width,\r
+                       int height,\r
+                       const video_format_desc& render_video_mode,\r
+                       const safe_ptr<ogl_device>& ogl,\r
+                       int generate_delay_millis,\r
+                       const thumbnail_creator& thumbnail_creator)\r
+               : media_path_(media_path)\r
+               , thumbnails_path_(thumbnails_path)\r
+               , width_(width)\r
+               , height_(height)\r
+               , ogl_(ogl)\r
+               , format_desc_(render_video_mode)\r
+               , output_(new thumbnail_output(generate_delay_millis))\r
+               , mixer_(new mixer(graph_, output_, format_desc_, ogl))\r
+               , thumbnail_creator_(thumbnail_creator)\r
+               , monitor_(monitor_factory.create(\r
+                               media_path,\r
+                               ALL,\r
+                               true,\r
+                               [this] (filesystem_event event, const boost::filesystem::wpath& file)\r
+                               {\r
+                                       this->on_file_event(event, file);\r
+                               },\r
+                               [this] (const std::set<boost::filesystem::wpath>& initial_files) \r
+                               {\r
+                                       this->on_initial_files(initial_files);\r
+                               }))\r
+       {\r
+               graph_->set_text(L"thumbnail-channel");\r
+               graph_->auto_reset();\r
+               diagnostics::register_graph(graph_);\r
+               //monitor_->initial_scan_completion().get();\r
+               //output_->sleep_millis = 2000;\r
+       }\r
+\r
+       void on_initial_files(const std::set<boost::filesystem::wpath>& initial_files)\r
+       {\r
+               using namespace boost::filesystem;\r
+\r
+               std::set<std::wstring> relative_without_extensions;\r
+               boost::transform(\r
+                               initial_files,\r
+                               std::insert_iterator<std::set<std::wstring>>(\r
+                                               relative_without_extensions,\r
+                                               relative_without_extensions.end()),\r
+                               boost::bind(&get_relative_without_extension, _1, media_path_));\r
+\r
+               for (wrecursive_directory_iterator iter(thumbnails_path_); iter != wrecursive_directory_iterator(); ++iter)\r
+               {\r
+                       auto& path = iter->path();\r
+\r
+                       if (!is_regular_file(path))\r
+                               continue;\r
+\r
+                       auto relative_without_extension = get_relative_without_extension(path, thumbnails_path_);\r
+                       bool no_corresponding_media_file = relative_without_extensions.find(relative_without_extension) \r
+                                       == relative_without_extensions.end();\r
+\r
+                       if (no_corresponding_media_file)\r
+                               remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
+               }\r
+       }\r
+\r
+       void generate(const std::wstring& media_file)\r
+       {\r
+               using namespace boost::filesystem;\r
+               auto base_file = media_path_ / media_file;\r
+               auto folder = base_file.parent_path();\r
+\r
+               for (wdirectory_iterator iter(folder); iter != wdirectory_iterator(); ++iter)\r
+               {\r
+                       auto stem = iter->path().stem();\r
+\r
+                       if (boost::iequals(stem, base_file.filename()))\r
+                               monitor_->reemmit(iter->path());\r
+               }\r
+       }\r
+\r
+       void generate_all()\r
+       {\r
+               monitor_->reemmit_all();\r
+       }\r
+\r
+       void on_file_event(filesystem_event event, const boost::filesystem::wpath& file)\r
+       {\r
+               switch (event)\r
+               {\r
+               case CREATED:\r
+                       if (needs_to_be_generated(file))\r
+                               generate_thumbnail(file);\r
+\r
+                       break;\r
+               case MODIFIED:\r
+                       generate_thumbnail(file);\r
+\r
+                       break;\r
+               case REMOVED:\r
+                       auto relative_without_extension = get_relative_without_extension(file, media_path_);\r
+                       boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
+\r
+                       break;\r
+               }\r
+       }\r
+\r
+       bool needs_to_be_generated(const boost::filesystem::wpath& file)\r
+       {\r
+               using namespace boost::filesystem;\r
+\r
+               auto png_file = thumbnails_path_ / (get_relative_without_extension(file, media_path_) + L".png");\r
+\r
+               if (!exists(png_file))\r
+                       return true;\r
+\r
+               std::time_t media_file_mtime;\r
+\r
+               try\r
+               {\r
+                       media_file_mtime = last_write_time(file);\r
+               }\r
+               catch (...)\r
+               {\r
+                       // Probably removed.\r
+                       return false;\r
+               }\r
+\r
+               try\r
+               {\r
+                       return media_file_mtime != last_write_time(png_file);\r
+               }\r
+               catch (...)\r
+               {\r
+                       // thumbnail probably removed.\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       void generate_thumbnail(const boost::filesystem::wpath& file)\r
+       {\r
+               auto media_file = get_relative_without_extension(file, media_path_);\r
+               auto png_file = thumbnails_path_ / (media_file + L".png");\r
+               boost::promise<void> thumbnail_ready;\r
+\r
+               {\r
+                       auto producer = frame_producer::empty();\r
+\r
+                       try\r
+                       {\r
+                               producer = create_thumbnail_producer(mixer_, media_file);\r
+                       }\r
+                       catch (const boost::thread_interrupted&)\r
+                       {\r
+                               throw;\r
+                       }\r
+                       catch (...)\r
+                       {\r
+                               CASPAR_LOG(debug) << L"Thumbnail producer failed to initialize for " << media_file;\r
+                               return;\r
+                       }\r
+\r
+                       if (producer == frame_producer::empty())\r
+                       {\r
+                               CASPAR_LOG(trace) << L"No appropriate thumbnail producer found for " << media_file;\r
+                               return;\r
+                       }\r
+\r
+                       boost::filesystem::create_directories(png_file.parent_path());\r
+                       output_->on_send = [this, &png_file] (const safe_ptr<read_frame>& frame)\r
+                       {\r
+                               thumbnail_creator_(frame, format_desc_, png_file, width_, height_);\r
+                       };\r
+\r
+                       std::map<int, safe_ptr<basic_frame>> frames;\r
+                       auto raw_frame = basic_frame::empty();\r
+\r
+                       try\r
+                       {\r
+                               raw_frame = producer->create_thumbnail_frame();\r
+                       }\r
+                       catch (const boost::thread_interrupted&)\r
+                       {\r
+                               throw;\r
+                       }\r
+                       catch (...)\r
+                       {\r
+                               CASPAR_LOG(debug) << L"Thumbnail producer failed to create thumbnail for " << media_file;\r
+                               return;\r
+                       }\r
+\r
+                       if (raw_frame == basic_frame::empty()\r
+                                       || raw_frame == basic_frame::empty()\r
+                                       || raw_frame == basic_frame::eof()\r
+                                       || raw_frame == basic_frame::late())\r
+                       {\r
+                               CASPAR_LOG(debug) << L"No thumbnail generated for " << media_file;\r
+                               return;\r
+                       }\r
+\r
+                       auto transformed_frame = make_safe<basic_frame>(raw_frame);\r
+                       transformed_frame->get_frame_transform().fill_scale[0] = static_cast<double>(width_) / format_desc_.width;\r
+                       transformed_frame->get_frame_transform().fill_scale[1] = static_cast<double>(height_) / format_desc_.height;\r
+                       frames.insert(std::make_pair(0, transformed_frame));\r
+\r
+                       std::shared_ptr<void> ticket(nullptr, [&thumbnail_ready](void*)\r
+                       {\r
+                               thumbnail_ready.set_value();\r
+                       });\r
+\r
+                       mixer_->send(std::make_pair(frames, ticket));\r
+                       ticket.reset();\r
+               }\r
+               thumbnail_ready.get_future().get();\r
+\r
+               if (boost::filesystem::exists(png_file))\r
+               {\r
+                       // Adjust timestamp to match source file.\r
+                       try\r
+                       {\r
+                               boost::filesystem::last_write_time(png_file, boost::filesystem::last_write_time(file));\r
+                               CASPAR_LOG(debug) << L"Generated thumbnail for " << media_file;\r
+                       }\r
+                       catch (...)\r
+                       {\r
+                               // One of the files was removed before the call to last_write_time.\r
+                       }\r
+               }\r
+               else\r
+                       CASPAR_LOG(debug) << L"No thumbnail generated for " << media_file;\r
+       }\r
+};\r
+\r
+thumbnail_generator::thumbnail_generator(\r
+               filesystem_monitor_factory& monitor_factory,\r
+               const boost::filesystem::wpath& media_path,\r
+               const boost::filesystem::wpath& thumbnails_path,\r
+               int width,\r
+               int height,\r
+               const video_format_desc& render_video_mode,\r
+               const safe_ptr<ogl_device>& ogl,\r
+               int generate_delay_millis,\r
+               const thumbnail_creator& thumbnail_creator)\r
+               : impl_(new implementation(\r
+                               monitor_factory,\r
+                               media_path,\r
+                               thumbnails_path,\r
+                               width, height,\r
+                               render_video_mode,\r
+                               ogl,\r
+                               generate_delay_millis,\r
+                               thumbnail_creator))\r
+{\r
+}\r
+\r
+thumbnail_generator::~thumbnail_generator()\r
+{\r
+}\r
+\r
+void thumbnail_generator::generate(const std::wstring& media_file)\r
+{\r
+       impl_->generate(media_file);\r
+}\r
+\r
+void thumbnail_generator::generate_all()\r
+{\r
+       impl_->generate_all();\r
+}\r
+\r
+}}\r
diff --git a/core/thumbnail_generator.h b/core/thumbnail_generator.h
new file mode 100644 (file)
index 0000000..2b9ec03
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/filesystem/filesystem_monitor.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class ogl_device;\r
+class read_frame;\r
+struct video_format_desc;\r
+\r
+typedef std::function<void (\r
+               const safe_ptr<read_frame>& frame,\r
+               const video_format_desc& format_desc,\r
+               const boost::filesystem::wpath& output_file,\r
+               int width,\r
+               int height)> thumbnail_creator;\r
+\r
+class thumbnail_generator : boost::noncopyable\r
+{\r
+public:\r
+       thumbnail_generator(\r
+                       filesystem_monitor_factory& monitor_factory,\r
+                       const boost::filesystem::wpath& media_path,\r
+                       const boost::filesystem::wpath& thumbnails_path,\r
+                       int width,\r
+                       int height,\r
+                       const video_format_desc& render_video_mode,\r
+                       const safe_ptr<ogl_device>& ogl,\r
+                       int generate_delay_millis,\r
+                       const thumbnail_creator& thumbnail_creator);\r
+       ~thumbnail_generator();\r
+       void generate(const std::wstring& media_file);\r
+       void generate_all();\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}\r
diff --git a/core/video_channel.cpp b/core/video_channel.cpp
new file mode 100644 (file)
index 0000000..4cad336
--- /dev/null
@@ -0,0 +1,128 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "video_channel.h"\r
+\r
+#include "video_format.h"\r
+\r
+#include "consumer/output.h"\r
+#include "mixer/mixer.h"\r
+#include "mixer/gpu/ogl_device.h"\r
+#include "producer/stage.h"\r
+\r
+#include <common/diagnostics/graph.h>\r
+#include <common/env.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct video_channel::implementation : boost::noncopyable\r
+{\r
+       const int                                                               index_;\r
+       video_format_desc                                               format_desc_;\r
+       const safe_ptr<ogl_device>                              ogl_;\r
+       const safe_ptr<diagnostics::graph>              graph_;\r
+\r
+       const safe_ptr<caspar::core::output>    output_;\r
+       const safe_ptr<caspar::core::mixer>             mixer_;\r
+       const safe_ptr<caspar::core::stage>             stage_;\r
+       \r
+public:\r
+       implementation(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl)  \r
+               : index_(index)\r
+               , format_desc_(format_desc)\r
+               , ogl_(ogl)\r
+               , output_(new caspar::core::output(graph_, format_desc, index))\r
+               , mixer_(new caspar::core::mixer(graph_, output_, format_desc, ogl))\r
+               , stage_(new caspar::core::stage(graph_, mixer_, format_desc))  \r
+       {\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+\r
+               for(int n = 0; n < std::max(1, env::properties().get(L"configuration.pipeline-tokens", 2)); ++n)\r
+                       stage_->spawn_token();\r
+\r
+               CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
+       }\r
+       \r
+       void set_video_format_desc(const video_format_desc& format_desc)\r
+       {\r
+               if(format_desc.format == core::video_format::invalid)\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Invalid video-format"));\r
+\r
+               try\r
+               {\r
+                       output_->set_video_format_desc(format_desc);\r
+                       mixer_->set_video_format_desc(format_desc);\r
+                       stage_->set_video_format_desc(format_desc);\r
+                       ogl_->gc();\r
+               }\r
+               catch(...)\r
+               {\r
+                       output_->set_video_format_desc(format_desc_);\r
+                       mixer_->set_video_format_desc(format_desc_);\r
+                       stage_->set_video_format_desc(format_desc_);\r
+                       throw;\r
+               }\r
+               format_desc_ = format_desc;\r
+       }\r
+               \r
+       std::wstring print() const\r
+       {\r
+               return L"video_channel[" + boost::lexical_cast<std::wstring>(index_) + L"|" +  format_desc_.name + L"]";\r
+       }\r
+\r
+       boost::property_tree::wptree info() const\r
+       {\r
+               boost::property_tree::wptree info;\r
+\r
+               auto stage_info  = stage_->info();\r
+               auto mixer_info  = mixer_->info();\r
+               auto output_info = output_->info();\r
+\r
+               stage_info.timed_wait(boost::posix_time::seconds(2));\r
+               mixer_info.timed_wait(boost::posix_time::seconds(2));\r
+               output_info.timed_wait(boost::posix_time::seconds(2));\r
+               \r
+               info.add(L"video-mode", format_desc_.name);\r
+               info.add_child(L"stage", stage_info.get());\r
+               info.add_child(L"mixer", mixer_info.get());\r
+               info.add_child(L"output", output_info.get());\r
+   \r
+               return info;                       \r
+       }\r
+};\r
+\r
+video_channel::video_channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new implementation(index, format_desc, ogl)){}\r
+safe_ptr<stage> video_channel::stage() { return impl_->stage_;} \r
+safe_ptr<mixer> video_channel::mixer() { return impl_->mixer_;} \r
+safe_ptr<output> video_channel::output() { return impl_->output_;} \r
+video_format_desc video_channel::get_video_format_desc() const{return impl_->format_desc_;}\r
+void video_channel::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
+boost::property_tree::wptree video_channel::info() const{return impl_->info();}\r
+int video_channel::index() const {return impl_->index_;}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/video_channel.h b/core/video_channel.h
new file mode 100644 (file)
index 0000000..c69bd63
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <boost/property_tree/ptree_fwd.hpp>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class stage;\r
+class mixer;\r
+class output;\r
+class ogl_device;\r
+struct video_format_desc;\r
+\r
+class video_channel : boost::noncopyable\r
+{\r
+public:\r
+       explicit video_channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
+\r
+       safe_ptr<stage> stage();\r
+       safe_ptr<mixer> mixer();\r
+       safe_ptr<output> output();\r
+       \r
+       video_format_desc get_video_format_desc() const;\r
+       void set_video_format_desc(const video_format_desc& format_desc);\r
+       \r
+       boost::property_tree::wptree info() const;\r
+\r
+       int index() const;\r
+\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/core/video_format.cpp b/core/video_format.cpp
new file mode 100644 (file)
index 0000000..1e1bff1
--- /dev/null
@@ -0,0 +1,94 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "video_format.h"\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/assign.hpp>\r
+\r
+#define DEFINE_VIDEOFORMATDESC(fmt, w, h, sw, sh, m, scale, duration, audio_samples, name) \\r
+{ \\r
+       (fmt), \\r
+       (w), \\r
+       (h), \\r
+       (sw),\\r
+       (sh),\\r
+       (m), \\r
+       ((double)scale/(double)duration),\\r
+       (scale),\\r
+       (duration),\\r
+       (m == field_mode::progressive ? 1 : 2),\\r
+       ((w)*(h)*4),\\r
+       (name),\\r
+       (48000),\\r
+       (2),\\r
+       (audio_samples)\\r
+}\r
+\r
+\r
+namespace caspar { namespace core {\r
+       \r
+const video_format_desc format_descs[video_format::count] =  \r
+{                                                                         \r
+       DEFINE_VIDEOFORMATDESC(video_format::pal                ,720,  576,  1024, 576,  field_mode::upper,                     25,             1,               boost::assign::list_of(3840),                                                  L"PAL"), \r
+       DEFINE_VIDEOFORMATDESC(video_format::ntsc               ,720,  486,  720,  540,  field_mode::lower,                     30000,  1001,    boost::assign::list_of(3204)(3202)(3204)(3202)(3204),  L"NTSC"), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x576p2500  ,1024, 576,  1024, 576,  field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"576p2500"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p2398  ,1280, 720,  1280, 720,  field_mode::progressive,       24000,  1001,    boost::assign::list_of(4004),                                                  L"720p2398"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p2400  ,1280, 720,  1280, 720,  field_mode::progressive,       24,             1,               boost::assign::list_of(4000),                                                  L"720p2400"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p2500  ,1280, 720,  1280, 720,  field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"720p2500"), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p5000  ,1280, 720,  1280, 720,  field_mode::progressive,       50,             1,               boost::assign::list_of(1920),                                                  L"720p5000"), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p2997  ,1280, 720,  1280, 720,  field_mode::progressive,       30000,  1001,    boost::assign::list_of(3204)(3202)(3204)(3202)(3204),  L"720p2997"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p5994  ,1280, 720,  1280, 720,  field_mode::progressive,       60000,  1001,    boost::assign::list_of(1602)(1601)(1602)(1601)(1602),  L"720p5994"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p3000  ,1280, 720,  1280, 720,  field_mode::progressive,       30,             1,               boost::assign::list_of(3200),                                                  L"720p3000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p6000  ,1280, 720,  1280, 720,  field_mode::progressive,       60,             1,               boost::assign::list_of(1600),                                                  L"720p6000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2398 ,1920, 1080, 1920, 1080, field_mode::progressive,       24000,  1001,    boost::assign::list_of(4004),                                                  L"1080p2398"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2400 ,1920, 1080, 1920, 1080, field_mode::progressive,       24,             1,               boost::assign::list_of(4000),                                                  L"1080p2400"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i5000 ,1920, 1080, 1920, 1080, field_mode::upper,                     25,             1,               boost::assign::list_of(3840),                                                  L"1080i5000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i5994 ,1920, 1080, 1920, 1080, field_mode::upper,                     30000,  1001,    boost::assign::list_of(3204)(3202)(3204)(3202)(3204),  L"1080i5994"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i6000 ,1920, 1080, 1920, 1080, field_mode::upper,                     30,             1,               boost::assign::list_of(3200),                                                  L"1080i6000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2500 ,1920, 1080, 1920, 1080, field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"1080p2500"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2997 ,1920, 1080, 1920, 1080, field_mode::progressive,       30000,  1001,    boost::assign::list_of(3204)(3202)(3204)(3202)(3204),  L"1080p2997"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p3000 ,1920, 1080, 1920, 1080, field_mode::progressive,       30,             1,               boost::assign::list_of(3200),                                                  L"1080p3000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p5000 ,1920, 1080, 1920, 1080, field_mode::progressive,       50,             1,               boost::assign::list_of(1920),                                                  L"1080p5000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p5994 ,1920, 1080, 1920, 1080, field_mode::progressive,       60000,  1001,    boost::assign::list_of(1602)(1601)(1602)(1601)(1602),  L"1080p5994"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p6000 ,1920, 1080, 1920, 1080, field_mode::progressive,       60,             1,               boost::assign::list_of(1600),                                                  L"1080p6000"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::invalid    ,0,             0,   0,         0,   field_mode::progressive,   1,              1,               boost::assign::list_of(1),                                                             L"invalid")\r
+};\r
+\r
+const video_format_desc& video_format_desc::get(video_format::type format)     \r
+{\r
+       return format_descs[format];\r
+}\r
+\r
+const video_format_desc& video_format_desc::get(const std::wstring& name)      \r
+{\r
+       for(int n = 0; n < video_format::invalid; ++n)\r
+       {\r
+               if(boost::iequals(format_descs[n].name, name))\r
+                       return format_descs[n];\r
+       }\r
+       return format_descs[video_format::invalid];\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/video_format.h b/core/video_format.h
new file mode 100644 (file)
index 0000000..48bbc1e
--- /dev/null
@@ -0,0 +1,126 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <vector>\r
+#include <string>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+struct video_format \r
+{ \r
+       enum type\r
+       {\r
+               pal = 0,\r
+               ntsc,\r
+               x576p2500,\r
+               x720p2500,\r
+               x720p5000,\r
+               x720p2398,\r
+               x720p2400,\r
+               x720p2997,\r
+               x720p5994,\r
+               x720p3000,\r
+               x720p6000,\r
+               x1080p2398,\r
+               x1080p2400,\r
+               x1080i5000,\r
+               x1080i5994,\r
+               x1080i6000,\r
+               x1080p2500,\r
+               x1080p2997,\r
+               x1080p3000,\r
+               x1080p5000,\r
+               x1080p5994,\r
+               x1080p6000,\r
+               invalid,\r
+               count\r
+       };\r
+};\r
+\r
+struct field_mode \r
+{ \r
+       enum type\r
+       {\r
+               empty           = 0,\r
+               lower           = 1,\r
+               upper           = 2,\r
+               progressive = 3 // NOTE: progressive == lower | upper;\r
+       };\r
+\r
+       static std::wstring print(field_mode::type value)\r
+       {\r
+               switch(value)\r
+               {\r
+                       case progressive:\r
+                               return L"progressive"; \r
+                       case lower:\r
+                               return L"lower";\r
+                       case upper:\r
+                               return L"upper";\r
+                       default:\r
+                               return L"invalid";\r
+               }\r
+       }\r
+};\r
+\r
+struct video_format_desc\r
+{\r
+       video_format::type              format;         // video output format\r
+\r
+       size_t                                  width;          // output frame width\r
+       size_t                                  height;         // output frame height\r
+       size_t                                  square_width;\r
+       size_t                                  square_height;\r
+       field_mode::type                field_mode;     // progressive, interlaced upper field first, interlaced lower field first\r
+       double                                  fps;            // actual framerate, e.g. i50 = 25 fps, p50 = 50 fps\r
+       size_t                                  time_scale;\r
+       size_t                                  duration;\r
+       size_t                                  field_count;\r
+       size_t                                  size;           // output frame size in bytes \r
+       std::wstring                    name;           // name of output format\r
+\r
+       size_t                                  audio_sample_rate;\r
+       size_t                                  audio_channels;\r
+       std::vector<size_t>             audio_cadence;\r
+\r
+       static const video_format_desc& get(video_format::type format);\r
+       static const video_format_desc& get(const std::wstring& name);\r
+       \r
+       bool operator==(const video_format_desc& lhs)\r
+       {\r
+               return format == lhs.format;\r
+       }\r
+\r
+       bool operator!=(const video_format_desc& lhs)\r
+       {\r
+               return !(*this == lhs);\r
+       }\r
+};\r
+\r
+inline std::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc)\r
+{\r
+       out << format_desc.name.c_str();\r
+       return out;\r
+}\r
+\r
+}}
\ No newline at end of file
similarity index 100%
rename from boost.7z
rename to dependencies/boost.7z
diff --git a/dependencies/ffmpeg 0.8/licenses/xavs.txt b/dependencies/ffmpeg 0.8/licenses/xavs.txt
new file mode 100644 (file)
index 0000000..818433e
--- /dev/null
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE\r
+                       Version 3, 29 June 2007\r
+\r
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+                            Preamble\r
+\r
+  The GNU General Public License is a free, copyleft license for\r
+software and other kinds of works.\r
+\r
+  The licenses for most software and other practical works are designed\r
+to take away your freedom to share and change the works.  By contrast,\r
+the GNU General Public License is intended to guarantee your freedom to\r
+share and change all versions of a program--to make sure it remains free\r
+software for all its users.  We, the Free Software Foundation, use the\r
+GNU General Public License for most of our software; it applies also to\r
+any other work released this way by its authors.  You can apply it to\r
+your programs, too.\r
+\r
+  When we speak of free software, we are referring to freedom, not\r
+price.  Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+them if you wish), that you receive source code or can get it if you\r
+want it, that you can change the software or use pieces of it in new\r
+free programs, and that you know you can do these things.\r
+\r
+  To protect your rights, we need to prevent others from denying you\r
+these rights or asking you to surrender the rights.  Therefore, you have\r
+certain responsibilities if you distribute copies of the software, or if\r
+you modify it: responsibilities to respect the freedom of others.\r
+\r
+  For example, if you distribute copies of such a program, whether\r
+gratis or for a fee, you must pass on to the recipients the same\r
+freedoms that you received.  You must make sure that they, too, receive\r
+or can get the source code.  And you must show them these terms so they\r
+know their rights.\r
+\r
+  Developers that use the GNU GPL protect your rights with two steps:\r
+(1) assert copyright on the software, and (2) offer you this License\r
+giving you legal permission to copy, distribute and/or modify it.\r
+\r
+  For the developers' and authors' protection, the GPL clearly explains\r
+that there is no warranty for this free software.  For both users' and\r
+authors' sake, the GPL requires that modified versions be marked as\r
+changed, so that their problems will not be attributed erroneously to\r
+authors of previous versions.\r
+\r
+  Some devices are designed to deny users access to install or run\r
+modified versions of the software inside them, although the manufacturer\r
+can do so.  This is fundamentally incompatible with the aim of\r
+protecting users' freedom to change the software.  The systematic\r
+pattern of such abuse occurs in the area of products for individuals to\r
+use, which is precisely where it is most unacceptable.  Therefore, we\r
+have designed this version of the GPL to prohibit the practice for those\r
+products.  If such problems arise substantially in other domains, we\r
+stand ready to extend this provision to those domains in future versions\r
+of the GPL, as needed to protect the freedom of users.\r
+\r
+  Finally, every program is threatened constantly by software patents.\r
+States should not allow patents to restrict development and use of\r
+software on general-purpose computers, but in those that do, we wish to\r
+avoid the special danger that patents applied to a free program could\r
+make it effectively proprietary.  To prevent this, the GPL assures that\r
+patents cannot be used to render the program non-free.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.\r
+\r
+                       TERMS AND CONDITIONS\r
+\r
+  0. Definitions.\r
+\r
+  "This License" refers to version 3 of the GNU General Public License.\r
+\r
+  "Copyright" also means copyright-like laws that apply to other kinds of\r
+works, such as semiconductor masks.\r
+\r
+  "The Program" refers to any copyrightable work licensed under this\r
+License.  Each licensee is addressed as "you".  "Licensees" and\r
+"recipients" may be individuals or organizations.\r
+\r
+  To "modify" a work means to copy from or adapt all or part of the work\r
+in a fashion requiring copyright permission, other than the making of an\r
+exact copy.  The resulting work is called a "modified version" of the\r
+earlier work or a work "based on" the earlier work.\r
+\r
+  A "covered work" means either the unmodified Program or a work based\r
+on the Program.\r
+\r
+  To "propagate" a work means to do anything with it that, without\r
+permission, would make you directly or secondarily liable for\r
+infringement under applicable copyright law, except executing it on a\r
+computer or modifying a private copy.  Propagation includes copying,\r
+distribution (with or without modification), making available to the\r
+public, and in some countries other activities as well.\r
+\r
+  To "convey" a work means any kind of propagation that enables other\r
+parties to make or receive copies.  Mere interaction with a user through\r
+a computer network, with no transfer of a copy, is not conveying.\r
+\r
+  An interactive user interface displays "Appropriate Legal Notices"\r
+to the extent that it includes a convenient and prominently visible\r
+feature that (1) displays an appropriate copyright notice, and (2)\r
+tells the user that there is no warranty for the work (except to the\r
+extent that warranties are provided), that licensees may convey the\r
+work under this License, and how to view a copy of this License.  If\r
+the interface presents a list of user commands or options, such as a\r
+menu, a prominent item in the list meets this criterion.\r
+\r
+  1. Source Code.\r
+\r
+  The "source code" for a work means the preferred form of the work\r
+for making modifications to it.  "Object code" means any non-source\r
+form of a work.\r
+\r
+  A "Standard Interface" means an interface that either is an official\r
+standard defined by a recognized standards body, or, in the case of\r
+interfaces specified for a particular programming language, one that\r
+is widely used among developers working in that language.\r
+\r
+  The "System Libraries" of an executable work include anything, other\r
+than the work as a whole, that (a) is included in the normal form of\r
+packaging a Major Component, but which is not part of that Major\r
+Component, and (b) serves only to enable use of the work with that\r
+Major Component, or to implement a Standard Interface for which an\r
+implementation is available to the public in source code form.  A\r
+"Major Component", in this context, means a major essential component\r
+(kernel, window system, and so on) of the specific operating system\r
+(if any) on which the executable work runs, or a compiler used to\r
+produce the work, or an object code interpreter used to run it.\r
+\r
+  The "Corresponding Source" for a work in object code form means all\r
+the source code needed to generate, install, and (for an executable\r
+work) run the object code and to modify the work, including scripts to\r
+control those activities.  However, it does not include the work's\r
+System Libraries, or general-purpose tools or generally available free\r
+programs which are used unmodified in performing those activities but\r
+which are not part of the work.  For example, Corresponding Source\r
+includes interface definition files associated with source files for\r
+the work, and the source code for shared libraries and dynamically\r
+linked subprograms that the work is specifically designed to require,\r
+such as by intimate data communication or control flow between those\r
+subprograms and other parts of the work.\r
+\r
+  The Corresponding Source need not include anything that users\r
+can regenerate automatically from other parts of the Corresponding\r
+Source.\r
+\r
+  The Corresponding Source for a work in source code form is that\r
+same work.\r
+\r
+  2. Basic Permissions.\r
+\r
+  All rights granted under this License are granted for the term of\r
+copyright on the Program, and are irrevocable provided the stated\r
+conditions are met.  This License explicitly affirms your unlimited\r
+permission to run the unmodified Program.  The output from running a\r
+covered work is covered by this License only if the output, given its\r
+content, constitutes a covered work.  This License acknowledges your\r
+rights of fair use or other equivalent, as provided by copyright law.\r
+\r
+  You may make, run and propagate covered works that you do not\r
+convey, without conditions so long as your license otherwise remains\r
+in force.  You may convey covered works to others for the sole purpose\r
+of having them make modifications exclusively for you, or provide you\r
+with facilities for running those works, provided that you comply with\r
+the terms of this License in conveying all material for which you do\r
+not control copyright.  Those thus making or running the covered works\r
+for you must do so exclusively on your behalf, under your direction\r
+and control, on terms that prohibit them from making any copies of\r
+your copyrighted material outside their relationship with you.\r
+\r
+  Conveying under any other circumstances is permitted solely under\r
+the conditions stated below.  Sublicensing is not allowed; section 10\r
+makes it unnecessary.\r
+\r
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\r
+\r
+  No covered work shall be deemed part of an effective technological\r
+measure under any applicable law fulfilling obligations under article\r
+11 of the WIPO copyright treaty adopted on 20 December 1996, or\r
+similar laws prohibiting or restricting circumvention of such\r
+measures.\r
+\r
+  When you convey a covered work, you waive any legal power to forbid\r
+circumvention of technological measures to the extent such circumvention\r
+is effected by exercising rights under this License with respect to\r
+the covered work, and you disclaim any intention to limit operation or\r
+modification of the work as a means of enforcing, against the work's\r
+users, your or third parties' legal rights to forbid circumvention of\r
+technological measures.\r
+\r
+  4. Conveying Verbatim Copies.\r
+\r
+  You may convey verbatim copies of the Program's source code as you\r
+receive it, in any medium, provided that you conspicuously and\r
+appropriately publish on each copy an appropriate copyright notice;\r
+keep intact all notices stating that this License and any\r
+non-permissive terms added in accord with section 7 apply to the code;\r
+keep intact all notices of the absence of any warranty; and give all\r
+recipients a copy of this License along with the Program.\r
+\r
+  You may charge any price or no price for each copy that you convey,\r
+and you may offer support or warranty protection for a fee.\r
+\r
+  5. Conveying Modified Source Versions.\r
+\r
+  You may convey a work based on the Program, or the modifications to\r
+produce it from the Program, in the form of source code under the\r
+terms of section 4, provided that you also meet all of these conditions:\r
+\r
+    a) The work must carry prominent notices stating that you modified\r
+    it, and giving a relevant date.\r
+\r
+    b) The work must carry prominent notices stating that it is\r
+    released under this License and any conditions added under section\r
+    7.  This requirement modifies the requirement in section 4 to\r
+    "keep intact all notices".\r
+\r
+    c) You must license the entire work, as a whole, under this\r
+    License to anyone who comes into possession of a copy.  This\r
+    License will therefore apply, along with any applicable section 7\r
+    additional terms, to the whole of the work, and all its parts,\r
+    regardless of how they are packaged.  This License gives no\r
+    permission to license the work in any other way, but it does not\r
+    invalidate such permission if you have separately received it.\r
+\r
+    d) If the work has interactive user interfaces, each must display\r
+    Appropriate Legal Notices; however, if the Program has interactive\r
+    interfaces that do not display Appropriate Legal Notices, your\r
+    work need not make them do so.\r
+\r
+  A compilation of a covered work with other separate and independent\r
+works, which are not by their nature extensions of the covered work,\r
+and which are not combined with it such as to form a larger program,\r
+in or on a volume of a storage or distribution medium, is called an\r
+"aggregate" if the compilation and its resulting copyright are not\r
+used to limit the access or legal rights of the compilation's users\r
+beyond what the individual works permit.  Inclusion of a covered work\r
+in an aggregate does not cause this License to apply to the other\r
+parts of the aggregate.\r
+\r
+  6. Conveying Non-Source Forms.\r
+\r
+  You may convey a covered work in object code form under the terms\r
+of sections 4 and 5, provided that you also convey the\r
+machine-readable Corresponding Source under the terms of this License,\r
+in one of these ways:\r
+\r
+    a) Convey the object code in, or embodied in, a physical product\r
+    (including a physical distribution medium), accompanied by the\r
+    Corresponding Source fixed on a durable physical medium\r
+    customarily used for software interchange.\r
+\r
+    b) Convey the object code in, or embodied in, a physical product\r
+    (including a physical distribution medium), accompanied by a\r
+    written offer, valid for at least three years and valid for as\r
+    long as you offer spare parts or customer support for that product\r
+    model, to give anyone who possesses the object code either (1) a\r
+    copy of the Corresponding Source for all the software in the\r
+    product that is covered by this License, on a durable physical\r
+    medium customarily used for software interchange, for a price no\r
+    more than your reasonable cost of physically performing this\r
+    conveying of source, or (2) access to copy the\r
+    Corresponding Source from a network server at no charge.\r
+\r
+    c) Convey individual copies of the object code with a copy of the\r
+    written offer to provide the Corresponding Source.  This\r
+    alternative is allowed only occasionally and noncommercially, and\r
+    only if you received the object code with such an offer, in accord\r
+    with subsection 6b.\r
+\r
+    d) Convey the object code by offering access from a designated\r
+    place (gratis or for a charge), and offer equivalent access to the\r
+    Corresponding Source in the same way through the same place at no\r
+    further charge.  You need not require recipients to copy the\r
+    Corresponding Source along with the object code.  If the place to\r
+    copy the object code is a network server, the Corresponding Source\r
+    may be on a different server (operated by you or a third party)\r
+    that supports equivalent copying facilities, provided you maintain\r
+    clear directions next to the object code saying where to find the\r
+    Corresponding Source.  Regardless of what server hosts the\r
+    Corresponding Source, you remain obligated to ensure that it is\r
+    available for as long as needed to satisfy these requirements.\r
+\r
+    e) Convey the object code using peer-to-peer transmission, provided\r
+    you inform other peers where the object code and Corresponding\r
+    Source of the work are being offered to the general public at no\r
+    charge under subsection 6d.\r
+\r
+  A separable portion of the object code, whose source code is excluded\r
+from the Corresponding Source as a System Library, need not be\r
+included in conveying the object code work.\r
+\r
+  A "User Product" is either (1) a "consumer product", which means any\r
+tangible personal property which is normally used for personal, family,\r
+or household purposes, or (2) anything designed or sold for incorporation\r
+into a dwelling.  In determining whether a product is a consumer product,\r
+doubtful cases shall be resolved in favor of coverage.  For a particular\r
+product received by a particular user, "normally used" refers to a\r
+typical or common use of that class of product, regardless of the status\r
+of the particular user or of the way in which the particular user\r
+actually uses, or expects or is expected to use, the product.  A product\r
+is a consumer product regardless of whether the product has substantial\r
+commercial, industrial or non-consumer uses, unless such uses represent\r
+the only significant mode of use of the product.\r
+\r
+  "Installation Information" for a User Product means any methods,\r
+procedures, authorization keys, or other information required to install\r
+and execute modified versions of a covered work in that User Product from\r
+a modified version of its Corresponding Source.  The information must\r
+suffice to ensure that the continued functioning of the modified object\r
+code is in no case prevented or interfered with solely because\r
+modification has been made.\r
+\r
+  If you convey an object code work under this section in, or with, or\r
+specifically for use in, a User Product, and the conveying occurs as\r
+part of a transaction in which the right of possession and use of the\r
+User Product is transferred to the recipient in perpetuity or for a\r
+fixed term (regardless of how the transaction is characterized), the\r
+Corresponding Source conveyed under this section must be accompanied\r
+by the Installation Information.  But this requirement does not apply\r
+if neither you nor any third party retains the ability to install\r
+modified object code on the User Product (for example, the work has\r
+been installed in ROM).\r
+\r
+  The requirement to provide Installation Information does not include a\r
+requirement to continue to provide support service, warranty, or updates\r
+for a work that has been modified or installed by the recipient, or for\r
+the User Product in which it has been modified or installed.  Access to a\r
+network may be denied when the modification itself materially and\r
+adversely affects the operation of the network or violates the rules and\r
+protocols for communication across the network.\r
+\r
+  Corresponding Source conveyed, and Installation Information provided,\r
+in accord with this section must be in a format that is publicly\r
+documented (and with an implementation available to the public in\r
+source code form), and must require no special password or key for\r
+unpacking, reading or copying.\r
+\r
+  7. Additional Terms.\r
+\r
+  "Additional permissions" are terms that supplement the terms of this\r
+License by making exceptions from one or more of its conditions.\r
+Additional permissions that are applicable to the entire Program shall\r
+be treated as though they were included in this License, to the extent\r
+that they are valid under applicable law.  If additional permissions\r
+apply only to part of the Program, that part may be used separately\r
+under those permissions, but the entire Program remains governed by\r
+this License without regard to the additional permissions.\r
+\r
+  When you convey a copy of a covered work, you may at your option\r
+remove any additional permissions from that copy, or from any part of\r
+it.  (Additional permissions may be written to require their own\r
+removal in certain cases when you modify the work.)  You may place\r
+additional permissions on material, added by you to a covered work,\r
+for which you have or can give appropriate copyright permission.\r
+\r
+  Notwithstanding any other provision of this License, for material you\r
+add to a covered work, you may (if authorized by the copyright holders of\r
+that material) supplement the terms of this License with terms:\r
+\r
+    a) Disclaiming warranty or limiting liability differently from the\r
+    terms of sections 15 and 16 of this License; or\r
+\r
+    b) Requiring preservation of specified reasonable legal notices or\r
+    author attributions in that material or in the Appropriate Legal\r
+    Notices displayed by works containing it; or\r
+\r
+    c) Prohibiting misrepresentation of the origin of that material, or\r
+    requiring that modified versions of such material be marked in\r
+    reasonable ways as different from the original version; or\r
+\r
+    d) Limiting the use for publicity purposes of names of licensors or\r
+    authors of the material; or\r
+\r
+    e) Declining to grant rights under trademark law for use of some\r
+    trade names, trademarks, or service marks; or\r
+\r
+    f) Requiring indemnification of licensors and authors of that\r
+    material by anyone who conveys the material (or modified versions of\r
+    it) with contractual assumptions of liability to the recipient, for\r
+    any liability that these contractual assumptions directly impose on\r
+    those licensors and authors.\r
+\r
+  All other non-permissive additional terms are considered "further\r
+restrictions" within the meaning of section 10.  If the Program as you\r
+received it, or any part of it, contains a notice stating that it is\r
+governed by this License along with a term that is a further\r
+restriction, you may remove that term.  If a license document contains\r
+a further restriction but permits relicensing or conveying under this\r
+License, you may add to a covered work material governed by the terms\r
+of that license document, provided that the further restriction does\r
+not survive such relicensing or conveying.\r
+\r
+  If you add terms to a covered work in accord with this section, you\r
+must place, in the relevant source files, a statement of the\r
+additional terms that apply to those files, or a notice indicating\r
+where to find the applicable terms.\r
+\r
+  Additional terms, permissive or non-permissive, may be stated in the\r
+form of a separately written license, or stated as exceptions;\r
+the above requirements apply either way.\r
+\r
+  8. Termination.\r
+\r
+  You may not propagate or modify a covered work except as expressly\r
+provided under this License.  Any attempt otherwise to propagate or\r
+modify it is void, and will automatically terminate your rights under\r
+this License (including any patent licenses granted under the third\r
+paragraph of section 11).\r
+\r
+  However, if you cease all violation of this License, then your\r
+license from a particular copyright holder is reinstated (a)\r
+provisionally, unless and until the copyright holder explicitly and\r
+finally terminates your license, and (b) permanently, if the copyright\r
+holder fails to notify you of the violation by some reasonable means\r
+prior to 60 days after the cessation.\r
+\r
+  Moreover, your license from a particular copyright holder is\r
+reinstated permanently if the copyright holder notifies you of the\r
+violation by some reasonable means, this is the first time you have\r
+received notice of violation of this License (for any work) from that\r
+copyright holder, and you cure the violation prior to 30 days after\r
+your receipt of the notice.\r
+\r
+  Termination of your rights under this section does not terminate the\r
+licenses of parties who have received copies or rights from you under\r
+this License.  If your rights have been terminated and not permanently\r
+reinstated, you do not qualify to receive new licenses for the same\r
+material under section 10.\r
+\r
+  9. Acceptance Not Required for Having Copies.\r
+\r
+  You are not required to accept this License in order to receive or\r
+run a copy of the Program.  Ancillary propagation of a covered work\r
+occurring solely as a consequence of using peer-to-peer transmission\r
+to receive a copy likewise does not require acceptance.  However,\r
+nothing other than this License grants you permission to propagate or\r
+modify any covered work.  These actions infringe copyright if you do\r
+not accept this License.  Therefore, by modifying or propagating a\r
+covered work, you indicate your acceptance of this License to do so.\r
+\r
+  10. Automatic Licensing of Downstream Recipients.\r
+\r
+  Each time you convey a covered work, the recipient automatically\r
+receives a license from the original licensors, to run, modify and\r
+propagate that work, subject to this License.  You are not responsible\r
+for enforcing compliance by third parties with this License.\r
+\r
+  An "entity transaction" is a transaction transferring control of an\r
+organization, or substantially all assets of one, or subdividing an\r
+organization, or merging organizations.  If propagation of a covered\r
+work results from an entity transaction, each party to that\r
+transaction who receives a copy of the work also receives whatever\r
+licenses to the work the party's predecessor in interest had or could\r
+give under the previous paragraph, plus a right to possession of the\r
+Corresponding Source of the work from the predecessor in interest, if\r
+the predecessor has it or can get it with reasonable efforts.\r
+\r
+  You may not impose any further restrictions on the exercise of the\r
+rights granted or affirmed under this License.  For example, you may\r
+not impose a license fee, royalty, or other charge for exercise of\r
+rights granted under this License, and you may not initiate litigation\r
+(including a cross-claim or counterclaim in a lawsuit) alleging that\r
+any patent claim is infringed by making, using, selling, offering for\r
+sale, or importing the Program or any portion of it.\r
+\r
+  11. Patents.\r
+\r
+  A "contributor" is a copyright holder who authorizes use under this\r
+License of the Program or a work on which the Program is based.  The\r
+work thus licensed is called the contributor's "contributor version".\r
+\r
+  A contributor's "essential patent claims" are all patent claims\r
+owned or controlled by the contributor, whether already acquired or\r
+hereafter acquired, that would be infringed by some manner, permitted\r
+by this License, of making, using, or selling its contributor version,\r
+but do not include claims that would be infringed only as a\r
+consequence of further modification of the contributor version.  For\r
+purposes of this definition, "control" includes the right to grant\r
+patent sublicenses in a manner consistent with the requirements of\r
+this License.\r
+\r
+  Each contributor grants you a non-exclusive, worldwide, royalty-free\r
+patent license under the contributor's essential patent claims, to\r
+make, use, sell, offer for sale, import and otherwise run, modify and\r
+propagate the contents of its contributor version.\r
+\r
+  In the following three paragraphs, a "patent license" is any express\r
+agreement or commitment, however denominated, not to enforce a patent\r
+(such as an express permission to practice a patent or covenant not to\r
+sue for patent infringement).  To "grant" such a patent license to a\r
+party means to make such an agreement or commitment not to enforce a\r
+patent against the party.\r
+\r
+  If you convey a covered work, knowingly relying on a patent license,\r
+and the Corresponding Source of the work is not available for anyone\r
+to copy, free of charge and under the terms of this License, through a\r
+publicly available network server or other readily accessible means,\r
+then you must either (1) cause the Corresponding Source to be so\r
+available, or (2) arrange to deprive yourself of the benefit of the\r
+patent license for this particular work, or (3) arrange, in a manner\r
+consistent with the requirements of this License, to extend the patent\r
+license to downstream recipients.  "Knowingly relying" means you have\r
+actual knowledge that, but for the patent license, your conveying the\r
+covered work in a country, or your recipient's use of the covered work\r
+in a country, would infringe one or more identifiable patents in that\r
+country that you have reason to believe are valid.\r
+\r
+  If, pursuant to or in connection with a single transaction or\r
+arrangement, you convey, or propagate by procuring conveyance of, a\r
+covered work, and grant a patent license to some of the parties\r
+receiving the covered work authorizing them to use, propagate, modify\r
+or convey a specific copy of the covered work, then the patent license\r
+you grant is automatically extended to all recipients of the covered\r
+work and works based on it.\r
+\r
+  A patent license is "discriminatory" if it does not include within\r
+the scope of its coverage, prohibits the exercise of, or is\r
+conditioned on the non-exercise of one or more of the rights that are\r
+specifically granted under this License.  You may not convey a covered\r
+work if you are a party to an arrangement with a third party that is\r
+in the business of distributing software, under which you make payment\r
+to the third party based on the extent of your activity of conveying\r
+the work, and under which the third party grants, to any of the\r
+parties who would receive the covered work from you, a discriminatory\r
+patent license (a) in connection with copies of the covered work\r
+conveyed by you (or copies made from those copies), or (b) primarily\r
+for and in connection with specific products or compilations that\r
+contain the covered work, unless you entered into that arrangement,\r
+or that patent license was granted, prior to 28 March 2007.\r
+\r
+  Nothing in this License shall be construed as excluding or limiting\r
+any implied license or other defenses to infringement that may\r
+otherwise be available to you under applicable patent law.\r
+\r
+  12. No Surrender of Others' Freedom.\r
+\r
+  If conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot convey a\r
+covered work so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you may\r
+not convey it at all.  For example, if you agree to terms that obligate you\r
+to collect a royalty for further conveying from those to whom you convey\r
+the Program, the only way you could satisfy both those terms and this\r
+License would be to refrain entirely from conveying the Program.\r
+\r
+  13. Use with the GNU Affero General Public License.\r
+\r
+  Notwithstanding any other provision of this License, you have\r
+permission to link or combine any covered work with a work licensed\r
+under version 3 of the GNU Affero General Public License into a single\r
+combined work, and to convey the resulting work.  The terms of this\r
+License will continue to apply to the part which is the covered work,\r
+but the special requirements of the GNU Affero General Public License,\r
+section 13, concerning interaction through a network will apply to the\r
+combination as such.\r
+\r
+  14. Revised Versions of this License.\r
+\r
+  The Free Software Foundation may publish revised and/or new versions of\r
+the GNU General Public License from time to time.  Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+\r
+  Each version is given a distinguishing version number.  If the\r
+Program specifies that a certain numbered version of the GNU General\r
+Public License "or any later version" applies to it, you have the\r
+option of following the terms and conditions either of that numbered\r
+version or of any later version published by the Free Software\r
+Foundation.  If the Program does not specify a version number of the\r
+GNU General Public License, you may choose any version ever published\r
+by the Free Software Foundation.\r
+\r
+  If the Program specifies that a proxy can decide which future\r
+versions of the GNU General Public License can be used, that proxy's\r
+public statement of acceptance of a version permanently authorizes you\r
+to choose that version for the Program.\r
+\r
+  Later license versions may give you additional or different\r
+permissions.  However, no additional obligations are imposed on any\r
+author or copyright holder as a result of your choosing to follow a\r
+later version.\r
+\r
+  15. Disclaimer of Warranty.\r
+\r
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\r
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\r
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\r
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\r
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\r
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\r
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
+\r
+  16. Limitation of Liability.\r
+\r
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\r
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\r
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\r
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\r
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\r
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\r
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\r
+SUCH DAMAGES.\r
+\r
+  17. Interpretation of Sections 15 and 16.\r
+\r
+  If the disclaimer of warranty and limitation of liability provided\r
+above cannot be given local legal effect according to their terms,\r
+reviewing courts shall apply local law that most closely approximates\r
+an absolute waiver of all civil liability in connection with the\r
+Program, unless a warranty or assumption of liability accompanies a\r
+copy of the Program in return for a fee.\r
+\r
+                     END OF TERMS AND CONDITIONS\r
+\r
+            How to Apply These Terms to Your New Programs\r
+\r
+  If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+\r
+  To do so, attach the following notices to the program.  It is safest\r
+to attach them to the start of each source file to most effectively\r
+state the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the program's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This program is free software: you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation, either version 3 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+  If the program does terminal interaction, make it output a short\r
+notice like this when it starts in an interactive mode:\r
+\r
+    <program>  Copyright (C) <year>  <name of author>\r
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+    This is free software, and you are welcome to redistribute it\r
+    under certain conditions; type `show c' for details.\r
+\r
+The hypothetical commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License.  Of course, your program's commands\r
+might be different; for a GUI interface, you would use an "about box".\r
+\r
+  You should also get your employer (if you work as a programmer) or school,\r
+if any, to sign a "copyright disclaimer" for the program, if necessary.\r
+For more information on this, and how to apply and follow the GNU GPL, see\r
+<http://www.gnu.org/licenses/>.\r
+\r
+  The GNU General Public License does not permit incorporating your program\r
+into proprietary programs.  If your program is a subroutine library, you\r
+may consider it more useful to permit linking proprietary applications with\r
+the library.  If this is what you want to do, use the GNU Lesser General\r
+Public License instead of this License.  But first, please read\r
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.\r
similarity index 100%
rename from tbb/CHANGES
rename to dependencies/tbb/CHANGES
similarity index 100%
rename from tbb/COPYING
rename to dependencies/tbb/COPYING
similarity index 100%
rename from tbb/README
rename to dependencies/tbb/README
similarity index 100%
rename from zlib/README.txt
rename to dependencies/zlib/README.txt
similarity index 100%
rename from zlib/USAGE.txt
rename to dependencies/zlib/USAGE.txt
similarity index 100%
rename from zlib/zlib1.dll
rename to dependencies/zlib/zlib1.dll
diff --git a/modules/bluefish/StdAfx.cpp b/modules/bluefish/StdAfx.cpp
new file mode 100644 (file)
index 0000000..da91e01
--- /dev/null
@@ -0,0 +1,29 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
\r
+// stdafx.cpp : source file that includes just the standard includes\r
+//     dma.pch will be the pre-compiled header\r
+//     stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
diff --git a/modules/bluefish/StdAfx.h b/modules/bluefish/StdAfx.h
new file mode 100644 (file)
index 0000000..fdc866f
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#define NOMINMAX\r
+\r
+#include <Windows.h>\r
+\r
+#include <memory>\r
+#include <array>\r
+#include <functional>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <deque>\r
+#include <queue>\r
+#include <string>\r
+#include <math.h>\r
+\r
+#include <common/utility/string.h>\r
+#include <common/memory/safe_ptr.h>\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include <common/log/Log.h>\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <assert.h>\r
diff --git a/modules/bluefish/bluefish.cpp b/modules/bluefish/bluefish.cpp
new file mode 100644 (file)
index 0000000..3c06a32
--- /dev/null
@@ -0,0 +1,88 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "bluefish.h"\r
+\r
+#include "consumer/bluefish_consumer.h"\r
+\r
+#include "util/blue_velvet.h"\r
+\r
+#include <common/log/log.h>\r
+#include <common/utility/string.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace bluefish {\r
+\r
+void init()\r
+{\r
+       try\r
+       {\r
+               blue_initialize();\r
+               core::register_consumer_factory([](const std::vector<std::wstring>& params)\r
+               {\r
+                       return create_consumer(params);\r
+               });\r
+       }\r
+       catch(...){}\r
+}\r
+\r
+std::wstring get_version()\r
+{\r
+       try\r
+       {\r
+               blue_initialize();\r
+       }\r
+       catch(...)\r
+       {\r
+               return L"Not found";\r
+       }\r
+\r
+       if(!BlueVelvetVersion)\r
+               return L"Unknown";\r
+\r
+       return widen(std::string(BlueVelvetVersion()));\r
+}\r
+\r
+std::vector<std::wstring> get_device_list()\r
+{\r
+       std::vector<std::wstring> devices;\r
+\r
+       try\r
+       {               \r
+               blue_initialize();\r
+               \r
+               auto blue = create_blue();\r
+\r
+               for(int n = 1; BLUE_PASS(blue->device_attach(n, FALSE)); ++n)\r
+               {                               \r
+                       devices.push_back(std::wstring(get_card_desc(*blue)) + L" [" + boost::lexical_cast<std::wstring>(n) + L"]");\r
+                       blue->device_detach();          \r
+               }\r
+       }\r
+       catch(...){}\r
+\r
+       return devices;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/bluefish.h b/modules/bluefish/bluefish.h
new file mode 100644 (file)
index 0000000..1718876
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace bluefish {\r
+\r
+void init();\r
+\r
+std::wstring get_version();\r
+std::vector<std::wstring> get_device_list();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/bluefish.vcxproj b/modules/bluefish/bluefish.vcxproj
new file mode 100644 (file)
index 0000000..e86cb24
--- /dev/null
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{69313D25-9F54-4FC9-9872-628A4DD79464}</ProjectGuid>\r
+    <RootNamespace>bluefish</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>bluefish</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\common;..\..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\..\dependencies\boost\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\common;..\..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\..\dependencies\boost\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\common;..\..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\..\dependencies\boost\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\common;..\..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\..\dependencies\boost\;..\..\dependencies\tbb\include\;..\..\dependencies\ffmpeg 0.8\include;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\..\dependencies\boost\stage\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\..\dependencies\boost\stage\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\..\dependencies\boost\stage\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\..\dependencies\boost\stage\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <AdditionalDependencies>\r
+      </AdditionalDependencies>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <AdditionalDependencies>\r
+      </AdditionalDependencies>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <AdditionalDependencies>\r
+      </AdditionalDependencies>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <AdditionalDependencies>\r
+      </AdditionalDependencies>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="bluefish.h" />\r
+    <ClInclude Include="consumer\bluefish_consumer.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\memory.h" />\r
+    <ClInclude Include="util\blue_velvet.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="bluefish.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\bluefish_consumer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="util\blue_velvet.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/bluefish/bluefish.vcxproj.filters b/modules/bluefish/bluefish.vcxproj.filters
new file mode 100644 (file)
index 0000000..a496bdc
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{8512c5f0-048f-48de-82ba-eb3ed1cf1177}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\util">\r
+      <UniqueIdentifier>{3de40b41-6c7c-4009-8159-b235e6d33ff6}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{0c50a039-638b-4d66-9b27-6ca0f75b5b63}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\bluefish_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\memory.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\blue_velvet.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="bluefish.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\bluefish_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="util\blue_velvet.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="bluefish.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/bluefish/consumer/bluefish_consumer.cpp b/modules/bluefish/consumer/bluefish_consumer.cpp
new file mode 100644 (file)
index 0000000..1dabf9e
--- /dev/null
@@ -0,0 +1,385 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
\r
+#include "../StdAfx.h"\r
+\r
+#include "bluefish_consumer.h"\r
+#include "../util/blue_velvet.h"\r
+#include "../util/memory.h"\r
+\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/memory/memclr.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/memory/memshfl.h>\r
+#include <common/utility/timer.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/mixer/audio/audio_util.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/timer.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <memory>\r
+#include <array>\r
+\r
+namespace caspar { namespace bluefish { \r
+                       \r
+struct bluefish_consumer : boost::noncopyable\r
+{\r
+       safe_ptr<CBlueVelvet4>                          blue_;\r
+       const unsigned int                                      device_index_;\r
+       const core::video_format_desc           format_desc_;\r
+       const int                                                       channel_index_;\r
+\r
+       const std::wstring                                      model_name_;\r
+\r
+       safe_ptr<diagnostics::graph>            graph_;\r
+       boost::timer                                            frame_timer_;\r
+       boost::timer                                            tick_timer_;\r
+       boost::timer                                            sync_timer_;    \r
+                       \r
+       unsigned int                                            vid_fmt_;\r
+\r
+       std::array<blue_dma_buffer_ptr, 4>      reserved_frames_;       \r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> frame_buffer_;\r
+       \r
+       const bool                                                      embedded_audio_;\r
+       const bool                                                      key_only_;\r
+               \r
+       executor                                                        executor_;\r
+public:\r
+       bluefish_consumer(const core::video_format_desc& format_desc, unsigned int device_index, bool embedded_audio, bool key_only, int channel_index) \r
+               : blue_(create_blue(device_index))\r
+               , device_index_(device_index)\r
+               , format_desc_(format_desc) \r
+               , channel_index_(channel_index)\r
+               , model_name_(get_card_desc(*blue_))\r
+               , vid_fmt_(get_video_mode(*blue_, format_desc))\r
+               , embedded_audio_(embedded_audio)\r
+               , key_only_(key_only)\r
+               , executor_(print())\r
+       {\r
+               executor_.set_capacity(1);\r
+\r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
+               graph_->set_color("sync-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+               graph_->set_color("frame-time", diagnostics::color(0.5f, 1.0f, 0.2f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+                       \r
+               //Setting output Video mode\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_MODE, vid_fmt_))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set videomode."));\r
+\r
+               //Select Update Mode for output\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_UPDATE_TYPE, UPD_FMT_FRAME))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set update type."));\r
+       \r
+               disable_video_output();\r
+\r
+               //Enable dual link output\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_DUAL_LINK_OUTPUT, 1)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to enable dual link."));\r
+\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_4224)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set dual link format type to 4:2:2:4."));\r
+                       \r
+               //Select output memory format\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_MEMORY_FORMAT, MEM_FMT_ARGB_PC))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set memory format."));\r
+               \r
+               //Select image orientation\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_IMAGE_ORIENTATION, ImageOrientation_Normal)))\r
+                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set image orientation to normal.");  \r
+\r
+               // Select data range\r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_RGB_DATA_RANGE, CGR_RANGE))) \r
+                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set RGB data range to CGR.");        \r
+               \r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_PREDEFINED_COLOR_MATRIX, vid_fmt_ == VID_FMT_PAL ? MATRIX_601_CGR : MATRIX_709_CGR)))\r
+                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set colormatrix to ") << (vid_fmt_ == VID_FMT_PAL ? TEXT("601 CGR") : TEXT("709 CGR")) << TEXT(".");\r
+\r
+               if(!embedded_audio_)\r
+               {\r
+                       if(BLUE_FAIL(set_card_property(blue_, EMBEDEDDED_AUDIO_OUTPUT, 0))) \r
+                               CASPAR_LOG(warning) << TEXT("BLUECARD ERROR: Failed to disable embedded audio.");                       \r
+                       CASPAR_LOG(info) << print() << TEXT(" Disabled embedded-audio.");\r
+               }\r
+               else\r
+               {\r
+                       if(BLUE_FAIL(set_card_property(blue_, EMBEDEDDED_AUDIO_OUTPUT, blue_emb_audio_enable | blue_emb_audio_group1_enable))) \r
+                               CASPAR_LOG(warning) << print() << TEXT(" Failed to enable embedded audio.");                    \r
+                       CASPAR_LOG(info) << print() << TEXT(" Enabled embedded-audio.");\r
+               }\r
+               \r
+               if (blue_->has_output_key()) \r
+               {\r
+                       int dummy = TRUE; int v4444 = FALSE; int invert = FALSE; int white = FALSE;\r
+                       blue_->set_output_key(dummy, v4444, invert, white);\r
+               }\r
+\r
+               if(blue_->GetHDCardType(device_index_) != CRD_HD_INVALID) \r
+                       blue_->Set_DownConverterSignalType(vid_fmt_ == VID_FMT_PAL ? SD_SDI : HD_SDI);  \r
+       \r
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_OUTPUT_ENGINE, VIDEO_ENGINE_FRAMESTORE))) \r
+                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set video engine."); \r
+               \r
+               enable_video_output();\r
+                                               \r
+               int n = 0;\r
+               boost::range::generate(reserved_frames_, [&]{return std::make_shared<blue_dma_buffer>(format_desc_.size, n++);});\r
+       }\r
+\r
+       ~bluefish_consumer()\r
+       {\r
+               try\r
+               {\r
+                       executor_.invoke([&]\r
+                       {\r
+                               disable_video_output();\r
+                               blue_->device_detach();         \r
+                       });\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+       \r
+       void enable_video_output()\r
+       {\r
+               if(!BLUE_PASS(set_card_property(blue_, VIDEO_BLACKGENERATOR, 0)))\r
+                       CASPAR_LOG(error) << print() << TEXT(" Failed to disable video output.");       \r
+       }\r
+\r
+       void disable_video_output()\r
+       {\r
+               blue_->video_playback_stop(0,0);\r
+               if(!BLUE_PASS(set_card_property(blue_, VIDEO_BLACKGENERATOR, 1)))\r
+                       CASPAR_LOG(error)<< print() << TEXT(" Failed to disable video output.");                \r
+       }\r
+       \r
+       boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               return executor_.begin_invoke([=]() -> bool\r
+               {\r
+                       try\r
+                       {       \r
+                               display_frame(frame);                           \r
+                               graph_->set_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
+                               tick_timer_.restart();\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+\r
+                       return true;\r
+               });\r
+       }\r
+\r
+       void display_frame(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               // Sync\r
+\r
+               sync_timer_.restart();\r
+               unsigned long n_field = 0;\r
+               blue_->wait_output_video_synch(UPD_FMT_FRAME, n_field);\r
+               graph_->set_value("sync-time", sync_timer_.elapsed()*format_desc_.fps*0.5);\r
+               \r
+               frame_timer_.restart();         \r
+\r
+               // Copy to local buffers\r
+               \r
+               if(!frame->image_data().empty())\r
+               {\r
+                       if(key_only_)                                           \r
+                               fast_memshfl(reserved_frames_.front()->image_data(), std::begin(frame->image_data()), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                       else\r
+                               fast_memcpy(reserved_frames_.front()->image_data(), std::begin(frame->image_data()), frame->image_data().size());\r
+               }\r
+               else\r
+                       fast_memclr(reserved_frames_.front()->image_data(), reserved_frames_.front()->image_size());\r
+                                                               \r
+\r
+               // Send and display\r
+\r
+               if(embedded_audio_)\r
+               {               \r
+                       auto frame_audio = core::audio_32_to_24(frame->audio_data());                   \r
+                       encode_hanc(reinterpret_cast<BLUE_UINT32*>(reserved_frames_.front()->hanc_data()), frame_audio.data(), frame->audio_data().size()/format_desc_.audio_channels, format_desc_.audio_channels);\r
+                                                               \r
+                       blue_->system_buffer_write_async(const_cast<uint8_t*>(reserved_frames_.front()->image_data()), \r
+                                                                                       reserved_frames_.front()->image_size(), \r
+                                                                                       nullptr, \r
+                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));\r
+\r
+                       blue_->system_buffer_write_async(reserved_frames_.front()->hanc_data(),\r
+                                                                                       reserved_frames_.front()->hanc_size(), \r
+                                                                                       nullptr,                 \r
+                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_HANC));\r
+\r
+                       if(BLUE_FAIL(blue_->render_buffer_update(BlueBuffer_Image_HANC(reserved_frames_.front()->id()))))\r
+                               CASPAR_LOG(warning) << print() << TEXT(" render_buffer_update failed.");\r
+               }\r
+               else\r
+               {\r
+                       blue_->system_buffer_write_async(const_cast<uint8_t*>(reserved_frames_.front()->image_data()),\r
+                                                                                       reserved_frames_.front()->image_size(), \r
+                                                                                       nullptr,                 \r
+                                                                                       BlueImage_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));\r
+                       \r
+                       if(BLUE_FAIL(blue_->render_buffer_update(BlueBuffer_Image(reserved_frames_.front()->id()))))\r
+                               CASPAR_LOG(warning) << print() << TEXT(" render_buffer_update failed.");\r
+               }\r
+\r
+               boost::range::rotate(reserved_frames_, std::begin(reserved_frames_)+1);\r
+               \r
+               graph_->set_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
+       }\r
+\r
+       void encode_hanc(BLUE_UINT32* hanc_data, void* audio_data, size_t audio_samples, size_t audio_nchannels)\r
+       {       \r
+               const auto sample_type = AUDIO_CHANNEL_24BIT | AUDIO_CHANNEL_LITTLEENDIAN;\r
+               const auto emb_audio_flag = blue_emb_audio_enable | blue_emb_audio_group1_enable;\r
+               \r
+               hanc_stream_info_struct hanc_stream_info;\r
+               memset(&hanc_stream_info, 0, sizeof(hanc_stream_info));\r
+               \r
+               hanc_stream_info.AudioDBNArray[0] = -1;\r
+               hanc_stream_info.AudioDBNArray[1] = -1;\r
+               hanc_stream_info.AudioDBNArray[2] = -1;\r
+               hanc_stream_info.AudioDBNArray[3] = -1;\r
+               hanc_stream_info.hanc_data_ptr    = hanc_data;\r
+               hanc_stream_info.video_mode               = vid_fmt_;           \r
+               \r
+               if (!is_epoch_card(*blue_))\r
+                       encode_hanc_frame(&hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);  \r
+               else\r
+                       encode_hanc_frame_ex(blue_->has_video_cardtype(), &hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);\r
+       }\r
+       \r
+       std::wstring print() const\r
+       {\r
+               return model_name_ + L" [" + boost::lexical_cast<std::wstring>(channel_index_) + L"-" + \r
+                       boost::lexical_cast<std::wstring>(device_index_) + L"|" +  format_desc_.name + L"]";\r
+       }\r
+};\r
+\r
+struct bluefish_consumer_proxy : public core::frame_consumer\r
+{\r
+       std::unique_ptr<bluefish_consumer>      consumer_;\r
+       const size_t                                            device_index_;\r
+       const bool                                                      embedded_audio_;\r
+       const bool                                                      key_only_;\r
+       std::vector<size_t>                                     audio_cadence_;\r
+public:\r
+\r
+       bluefish_consumer_proxy(size_t device_index, bool embedded_audio, bool key_only)\r
+               : device_index_(device_index)\r
+               , embedded_audio_(embedded_audio)\r
+               , key_only_(key_only)\r
+       {\r
+       }\r
+       \r
+       ~bluefish_consumer_proxy()\r
+       {\r
+               if(consumer_)\r
+               {\r
+                       auto str = print();\r
+                       consumer_.reset();\r
+                       CASPAR_LOG(info) << str << L" Successfully Uninitialized.";     \r
+               }\r
+       }\r
+\r
+       // frame_consumer\r
+       \r
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_, key_only_, channel_index));\r
+               audio_cadence_ = format_desc.audio_cadence;\r
+               CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
+       }\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override\r
+       {\r
+               CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
+               boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+\r
+               return consumer_->send(frame);\r
+       }\r
+               \r
+       virtual std::wstring print() const override\r
+       {\r
+               return consumer_ ? consumer_->print() : L"[bluefish_consumer]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"bluefish-consumer");\r
+               info.add(L"key-only", key_only_);\r
+               info.add(L"device", device_index_);\r
+               info.add(L"embedded-audio", embedded_audio_);\r
+               return info;\r
+       }\r
+\r
+       size_t buffer_depth() const override\r
+       {\r
+               return 1;\r
+       }\r
+       \r
+       virtual int index() const override\r
+       {\r
+               return 400 + device_index_;\r
+       }\r
+};     \r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 1 || params[0] != L"BLUEFISH")\r
+               return core::frame_consumer::empty();\r
+               \r
+       const auto device_index = params.size() > 1 ? lexical_cast_or_default<int>(params[1], 1) : 1;\r
+\r
+       const auto embedded_audio = std::find(params.begin(), params.end(), L"EMBEDDED_AUDIO") != params.end();\r
+       const auto key_only               = std::find(params.begin(), params.end(), L"KEY_ONLY")           != params.end();\r
+\r
+       return make_safe<bluefish_consumer_proxy>(device_index, embedded_audio, key_only);\r
+}\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree) \r
+{      \r
+       const auto device_index         = ptree.get(L"device",                  1);\r
+       const auto embedded_audio       = ptree.get(L"embedded-audio",  false);\r
+       const auto key_only                     = ptree.get(L"key-only",                false);\r
+\r
+       return make_safe<bluefish_consumer_proxy>(device_index, embedded_audio, key_only);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/consumer/bluefish_consumer.h b/modules/bluefish/consumer/bluefish_consumer.h
new file mode 100644 (file)
index 0000000..2be5389
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+}\r
+        \r
+namespace bluefish {\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/util/blue_velvet.cpp b/modules/bluefish/util/blue_velvet.cpp
new file mode 100644 (file)
index 0000000..0eefd39
--- /dev/null
@@ -0,0 +1,211 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "blue_velvet.h"\r
+\r
+#include <common/utility/string.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+namespace caspar { namespace bluefish {\r
+       \r
+CBlueVelvet4* (*BlueVelvetFactory4)() = nullptr;\r
+void (*BlueVelvetDestroy)(CBlueVelvet4* pObj) = nullptr;\r
+const char*    (*BlueVelvetVersion)() = nullptr;\r
+BLUE_UINT32 (*encode_hanc_frame)(struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr,BLUE_UINT32 no_audio_ch,BLUE_UINT32 no_audio_samples,BLUE_UINT32 nTypeOfSample,BLUE_UINT32 emb_audio_flag) = nullptr;\r
+BLUE_UINT32 (*encode_hanc_frame_ex)(BLUE_UINT32 card_type, struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr, BLUE_UINT32 no_audio_ch,    BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag) = nullptr;\r
+\r
+void blue_velvet_initialize()\r
+{\r
+#ifdef _DEBUG\r
+       std::string module_str = "BlueVelvet3_d.dll";\r
+#else\r
+       std::string module_str = "BlueVelvet3.dll";\r
+#endif\r
+\r
+       auto module = LoadLibrary(widen(module_str).c_str());\r
+       if(!module)\r
+               LoadLibrary(widen(std::string(getenv("SystemDrive")) + "\\Program Files\\Bluefish444\\Driver\\" + module_str).c_str());\r
+       if(!module)\r
+               LoadLibrary(widen(std::string(getenv("SystemDrive")) + "\\Program Files (x86)\\BlueFish444\\Driver\\" + module_str).c_str());\r
+       if(!module)\r
+               BOOST_THROW_EXCEPTION(file_not_found() << msg_info("Could not find BlueVelvet3.dll. Required drivers are not installed."));\r
+       static std::shared_ptr<void> lib(module, FreeLibrary);\r
+       BlueVelvetFactory4 = reinterpret_cast<decltype(BlueVelvetFactory4)>(GetProcAddress(module, "BlueVelvetFactory4"));\r
+       BlueVelvetDestroy  = reinterpret_cast<decltype(BlueVelvetDestroy)>(GetProcAddress(module, "BlueVelvetDestroy"));\r
+       BlueVelvetVersion  = reinterpret_cast<decltype(BlueVelvetVersion)>(GetProcAddress(module, "BlueVelvetVersion"));\r
+}\r
+\r
+void blue_hanc_initialize()\r
+{\r
+#ifdef _DEBUG\r
+       std::string module_str = "BlueHancUtils_d.dll";\r
+#else\r
+       std::string module_str = "BlueHancUtils.dll";\r
+#endif\r
+       \r
+       auto module = LoadLibrary(widen(module_str).c_str());\r
+       if(!module)\r
+               LoadLibrary(widen(std::string(getenv("SystemDrive")) + "\\Program Files\\Bluefish444\\Driver\\" + module_str).c_str());\r
+       if(!module)\r
+               LoadLibrary(widen(std::string(getenv("SystemDrive")) + "\\Program Files (x86)\\BlueFish444\\Driver\\" + module_str).c_str());\r
+       if(!module)\r
+               BOOST_THROW_EXCEPTION(file_not_found() << msg_info("Could not find BlueHancUtils.dll. Required drivers are not installed."));\r
+       static std::shared_ptr<void> lib(module, FreeLibrary);\r
+       encode_hanc_frame        = reinterpret_cast<decltype(encode_hanc_frame)>(GetProcAddress(module, "encode_hanc_frame"));\r
+       encode_hanc_frame_ex = reinterpret_cast<decltype(encode_hanc_frame_ex)>(GetProcAddress(module, "encode_hanc_frame_ex"));\r
+}\r
+\r
+void blue_initialize()\r
+{\r
+       blue_hanc_initialize();\r
+       blue_velvet_initialize();\r
+}\r
+\r
+EVideoMode vid_fmt_from_video_format(const core::video_format::type& fmt) \r
+{\r
+       switch(fmt)\r
+       {\r
+       case core::video_format::pal:                   return VID_FMT_PAL;\r
+       case core::video_format::ntsc:                  return VID_FMT_NTSC;\r
+       case core::video_format::x576p2500:             return VID_FMT_INVALID; //not supported\r
+       case core::video_format::x720p2398:             return VID_FMT_720P_2398;\r
+       case core::video_format::x720p2400:             return VID_FMT_720P_2400;\r
+       case core::video_format::x720p2500:             return VID_FMT_720P_2500;\r
+       case core::video_format::x720p5000:             return VID_FMT_720P_5000;\r
+       case core::video_format::x720p2997:             return VID_FMT_720P_2997;\r
+       case core::video_format::x720p5994:             return VID_FMT_720P_5994;\r
+       case core::video_format::x720p3000:             return VID_FMT_720P_3000;\r
+       case core::video_format::x720p6000:             return VID_FMT_720P_6000;\r
+       case core::video_format::x1080p2398:    return VID_FMT_1080P_2397;\r
+       case core::video_format::x1080p2400:    return VID_FMT_1080P_2400;\r
+       case core::video_format::x1080i5000:    return VID_FMT_1080I_5000;\r
+       case core::video_format::x1080i5994:    return VID_FMT_1080I_5994;\r
+       case core::video_format::x1080i6000:    return VID_FMT_1080I_6000;\r
+       case core::video_format::x1080p2500:    return VID_FMT_1080P_2500;\r
+       case core::video_format::x1080p2997:    return VID_FMT_1080P_2997;\r
+       case core::video_format::x1080p3000:    return VID_FMT_1080P_3000;\r
+       case core::video_format::x1080p5000:    return VID_FMT_1080P_5000;\r
+       case core::video_format::x1080p5994:    return VID_FMT_1080P_5994;\r
+       case core::video_format::x1080p6000:    return VID_FMT_1080P_6000;\r
+       default:                                                                return VID_FMT_INVALID;\r
+       }\r
+}\r
+\r
+bool is_epoch_card(CBlueVelvet4& blue)\r
+{\r
+       switch(blue.has_video_cardtype())\r
+       {\r
+       case CRD_BLUE_EPOCH_HORIZON:\r
+       case CRD_BLUE_EPOCH_CORE:\r
+       case CRD_BLUE_EPOCH_ULTRA:\r
+       case CRD_BLUE_EPOCH_2K_HORIZON:\r
+       case CRD_BLUE_EPOCH_2K_CORE:\r
+       case CRD_BLUE_EPOCH_2K_ULTRA:\r
+       case CRD_BLUE_CREATE_HD:\r
+       case CRD_BLUE_CREATE_2K:\r
+       case CRD_BLUE_CREATE_2K_ULTRA:\r
+       case CRD_BLUE_SUPER_NOVA:\r
+               return true;\r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+std::wstring get_card_desc(CBlueVelvet4& blue)\r
+{\r
+       switch(blue.has_video_cardtype()) \r
+       {\r
+       case CRD_BLUEDEEP_LT:                           return L"Deepblue LT";// D64 Lite\r
+       case CRD_BLUEDEEP_SD:                           return L"Iridium SD";// Iridium SD\r
+       case CRD_BLUEDEEP_AV:                           return L"Iridium AV";// Iridium AV\r
+       case CRD_BLUEDEEP_IO:                           return L"Deepblue IO";// D64 Full\r
+       case CRD_BLUEWILD_AV:                           return L"Wildblue AV";// D64 AV\r
+       case CRD_IRIDIUM_HD:                            return L"Iridium HD";// * Iridium HD\r
+       case CRD_BLUEWILD_RT:                           return L"Wildblue RT";// D64 RT\r
+       case CRD_BLUEWILD_HD:                           return L"Wildblue HD";// * BadAss G2\r
+       case CRD_REDDEVIL:                                      return L"Iridium Full";// Iridium Full\r
+       case CRD_BLUEDEEP_HD:   \r
+       case CRD_BLUEDEEP_HDS:                          return L"Reserved for \"BasAss G2";// * BadAss G2 variant, proposed, reserved\r
+       case CRD_BLUE_ENVY:                                     return L"Blue Envy"; // Mini Din \r
+       case CRD_BLUE_PRIDE:                            return L"Blue Pride";//Mini Din Output \r
+       case CRD_BLUE_GREED:                            return L"Blue Greed";\r
+       case CRD_BLUE_INGEST:                           return L"Blue Ingest";\r
+       case CRD_BLUE_SD_DUALLINK:                      return L"Blue SD Duallink";\r
+       case CRD_BLUE_CATALYST:                         return L"Blue Catalyst";\r
+       case CRD_BLUE_SD_DUALLINK_PRO:          return L"Blue SD Duallink Pro";\r
+       case CRD_BLUE_SD_INGEST_PRO:            return L"Blue SD Ingest pro";\r
+       case CRD_BLUE_SD_DEEPBLUE_LITE_PRO:     return L"Blue SD Deepblue lite Pro";\r
+       case CRD_BLUE_SD_SINGLELINK_PRO:        return L"Blue SD Singlelink Pro";\r
+       case CRD_BLUE_SD_IRIDIUM_AV_PRO:        return L"Blue SD Iridium AV Pro";\r
+       case CRD_BLUE_SD_FIDELITY:                      return L"Blue SD Fidelity";\r
+       case CRD_BLUE_SD_FOCUS:                         return L"Blue SD Focus";\r
+       case CRD_BLUE_SD_PRIME:                         return L"Blue SD Prime";\r
+       case CRD_BLUE_EPOCH_2K_CORE:            return L"Blue Epoch 2K Core";\r
+       case CRD_BLUE_EPOCH_2K_ULTRA:           return L"Blue Epoch 2K Ultra";\r
+       case CRD_BLUE_EPOCH_HORIZON:            return L"Blue Epoch Horizon";\r
+       case CRD_BLUE_EPOCH_CORE:                       return L"Blue Epoch Core";\r
+       case CRD_BLUE_EPOCH_ULTRA:                      return L"Blue Epoch Ultra";\r
+       case CRD_BLUE_CREATE_HD:                        return L"Blue Create HD";\r
+       case CRD_BLUE_CREATE_2K:                        return L"Blue Create 2K";\r
+       case CRD_BLUE_CREATE_2K_ULTRA:          return L"Blue Create 2K Ultra";\r
+       default:                                                        return L"Unknown";\r
+       }\r
+}\r
+\r
+EVideoMode get_video_mode(CBlueVelvet4& blue, const core::video_format_desc& format_desc)\r
+{\r
+       EVideoMode vid_fmt = VID_FMT_INVALID;\r
+       auto desiredVideoFormat = vid_fmt_from_video_format(format_desc.format);\r
+       int videoModeCount = blue.count_video_mode();\r
+       for(int videoModeIndex = 1; videoModeIndex <= videoModeCount; ++videoModeIndex) \r
+       {\r
+               EVideoMode videoMode = blue.enum_video_mode(videoModeIndex);\r
+               if(videoMode == desiredVideoFormat) \r
+                       vid_fmt = videoMode;                    \r
+       }\r
+       if(vid_fmt == VID_FMT_INVALID)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("video-mode not supported.") << arg_value_info(narrow(format_desc.name)));\r
+\r
+       return vid_fmt;\r
+}\r
+\r
+safe_ptr<CBlueVelvet4> create_blue()\r
+{\r
+       if(!BlueVelvetFactory4 || !encode_hanc_frame || !encode_hanc_frame)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Bluefish drivers not found."));\r
+\r
+       return safe_ptr<CBlueVelvet4>(BlueVelvetFactory4(), BlueVelvetDestroy);\r
+}\r
+\r
+safe_ptr<CBlueVelvet4> create_blue(size_t device_index)\r
+{\r
+       auto blue = create_blue();\r
+       \r
+       if(BLUE_FAIL(blue->device_attach(device_index, FALSE))) \r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to attach device."));\r
+\r
+       return blue;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/util/blue_velvet.h b/modules/bluefish/util/blue_velvet.h
new file mode 100644 (file)
index 0000000..7895cd4
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <Windows.h>\r
+\r
+#include <BlueVelvet4.h>\r
+#include <BlueHancUtils.h>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/exception/exceptions.h>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+\r
+struct video_format_desc;\r
+\r
+}\r
+\r
+namespace bluefish {\r
+\r
+extern const char* (*BlueVelvetVersion)();\r
+extern BLUE_UINT32 (*encode_hanc_frame)(struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr,BLUE_UINT32 no_audio_ch,BLUE_UINT32 no_audio_samples,BLUE_UINT32 nTypeOfSample,BLUE_UINT32 emb_audio_flag);\r
+extern BLUE_UINT32 (*encode_hanc_frame_ex)(BLUE_UINT32 card_type, struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr, BLUE_UINT32 no_audio_ch,     BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag);\r
+\r
+void blue_initialize();\r
+\r
+safe_ptr<CBlueVelvet4> create_blue();\r
+safe_ptr<CBlueVelvet4> create_blue(size_t device_index);\r
+bool is_epoch_card(CBlueVelvet4& blue);\r
+std::wstring get_card_desc(CBlueVelvet4& blue);\r
+EVideoMode get_video_mode(CBlueVelvet4& blue, const core::video_format_desc& format_desc);\r
+\r
+template<typename T>\r
+int set_card_property(T& pSdk, ULONG prop, ULONG value)\r
+{\r
+       VARIANT variantValue;\r
+       variantValue.vt  = VT_UI4;\r
+       variantValue.ulVal = value;\r
+       return (pSdk->SetCardProperty(prop,variantValue));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/bluefish/util/memory.h b/modules/bluefish/util/memory.h
new file mode 100644 (file)
index 0000000..d9ffeba
--- /dev/null
@@ -0,0 +1,64 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <Windows.h>\r
+\r
+#include <BlueVelvet4.h>\r
+\r
+#include <common/memory/page_locked_allocator.h>\r
+\r
+#include <vector>\r
+\r
+namespace caspar { namespace bluefish {\r
+       \r
+static const size_t MAX_HANC_BUFFER_SIZE = 256*1024;\r
+static const size_t MAX_VBI_BUFFER_SIZE = 36*1920*4;\r
+\r
+struct blue_dma_buffer\r
+{\r
+public:\r
+       blue_dma_buffer(int image_size, int id) \r
+               : id_(id)\r
+               , image_size_(image_size)\r
+               , hanc_size_(MAX_HANC_BUFFER_SIZE)\r
+               , image_buffer_(image_size_)\r
+               , hanc_buffer_(hanc_size_){}\r
+                       \r
+       int id() const {return id_;}\r
+\r
+       PBYTE image_data() { return image_buffer_.data(); }\r
+       PBYTE hanc_data() { return hanc_buffer_.data(); }\r
+\r
+       size_t image_size() const { return image_size_; }\r
+       size_t hanc_size() const { return hanc_size_; }\r
+\r
+private:       \r
+       int id_;\r
+       size_t image_size_;\r
+       size_t hanc_size_;\r
+       std::vector<BYTE, page_locked_allocator<BYTE>> image_buffer_;   \r
+       std::vector<BYTE, page_locked_allocator<BYTE>> hanc_buffer_;\r
+};\r
+typedef std::shared_ptr<blue_dma_buffer> blue_dma_buffer_ptr;\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/decklink/StdAfx.cpp b/modules/decklink/StdAfx.cpp
new file mode 100644 (file)
index 0000000..61ffa69
--- /dev/null
@@ -0,0 +1,25 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
diff --git a/modules/decklink/StdAfx.h b/modules/decklink/StdAfx.h
new file mode 100644 (file)
index 0000000..ee2bab4
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#define NOMINMAX\r
+\r
+#include <Windows.h>\r
+\r
+#include <algorithm>\r
+#include <array>\r
+#include <assert.h>\r
+#include <deque>\r
+#include <functional>\r
+#include <math.h>\r
+#include <memory>\r
+#include <queue>\r
+#include <string>\r
+#include <vector>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+\r
+#include "../common/memory/safe_ptr.h"\r
+#include "../common/utility/string.h"\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include "../common/exception/exceptions.h"\r
+#include "../common/exception/win32_exception.h"\r
+#include "../common/log/Log.h"\r
diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp
new file mode 100644 (file)
index 0000000..5993492
--- /dev/null
@@ -0,0 +1,696 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
\r
+#include "decklink_consumer.h"\r
+\r
+#include "../util/util.h"\r
+\r
+#include "../interop/DeckLinkAPI_h.h"\r
+\r
+#include <core/mixer/read_frame.h>\r
+\r
+#include <common/concurrency/com_context.h>\r
+#include <common/concurrency/future_util.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/memory/memclr.h>\r
+#include <common/memory/memshfl.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+namespace caspar { namespace decklink { \r
+       \r
+struct configuration\r
+{\r
+       enum keyer_t\r
+       {\r
+               internal_keyer,\r
+               external_keyer,\r
+               default_keyer\r
+       };\r
+\r
+       enum latency_t\r
+       {\r
+               low_latency,\r
+               normal_latency,\r
+               default_latency\r
+       };\r
+\r
+       size_t          device_index;\r
+       bool            embedded_audio;\r
+       keyer_t         keyer;\r
+       latency_t       latency;\r
+       bool            key_only;\r
+       size_t          base_buffer_depth;\r
+       \r
+       configuration()\r
+               : device_index(1)\r
+               , embedded_audio(false)\r
+               , keyer(default_keyer)\r
+               , latency(default_latency)\r
+               , key_only(false)\r
+               , base_buffer_depth(3)\r
+       {\r
+       }\r
+       \r
+       size_t buffer_depth() const\r
+       {\r
+               return base_buffer_depth + (latency == low_latency ? 0 : 1) + (embedded_audio ? 1 : 0);\r
+       }\r
+};\r
+\r
+class decklink_frame : public IDeckLinkVideoFrame\r
+{\r
+       tbb::atomic<int>                                                                                        ref_count_;\r
+       std::shared_ptr<core::read_frame>                                                       frame_;\r
+       const core::video_format_desc                                                           format_desc_;\r
+\r
+       const bool                                                                                                      key_only_;\r
+       std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> data_;\r
+public:\r
+       decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
+               : frame_(frame)\r
+               , format_desc_(format_desc)\r
+               , key_only_(key_only)\r
+       {\r
+               ref_count_ = 0;\r
+       }\r
+       \r
+       // IUnknown\r
+\r
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))             \r
+       {\r
+               return E_NOINTERFACE;\r
+       }\r
+       \r
+       STDMETHOD_(ULONG,                       AddRef())                       \r
+       {\r
+               return ++ref_count_;\r
+       }\r
+\r
+       STDMETHOD_(ULONG,                       Release())                      \r
+       {\r
+               if(--ref_count_ == 0)\r
+                       delete this;\r
+               return ref_count_;\r
+       }\r
+\r
+       // IDecklinkVideoFrame\r
+\r
+       STDMETHOD_(long,                        GetWidth())                     {return format_desc_.width;}        \r
+    STDMETHOD_(long,                   GetHeight())            {return format_desc_.height;}        \r
+    STDMETHOD_(long,                   GetRowBytes())          {return format_desc_.width*4;}        \r
+       STDMETHOD_(BMDPixelFormat,      GetPixelFormat())       {return bmdFormat8BitBGRA;}        \r
+    STDMETHOD_(BMDFrameFlags,  GetFlags())                     {return bmdFrameFlagDefault;}\r
+        \r
+    STDMETHOD(GetBytes(void** buffer))\r
+       {\r
+               try\r
+               {\r
+                       if(static_cast<size_t>(frame_->image_data().size()) != format_desc_.size)\r
+                       {\r
+                               data_.resize(format_desc_.size, 0);\r
+                               *buffer = data_.data();\r
+                       }\r
+                       else if(key_only_)\r
+                       {\r
+                               if(data_.empty())\r
+                               {\r
+                                       data_.resize(frame_->image_data().size());\r
+                                       fast_memshfl(data_.data(), frame_->image_data().begin(), frame_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                               }\r
+                               *buffer = data_.data();\r
+                       }\r
+                       else\r
+                               *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       return E_FAIL;\r
+               }\r
+\r
+               return S_OK;\r
+       }\r
+        \r
+    STDMETHOD(GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode)){return S_FALSE;}        \r
+    STDMETHOD(GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary))                {return S_FALSE;}\r
+\r
+       // decklink_frame       \r
+\r
+       const boost::iterator_range<const int32_t*> audio_data()\r
+       {\r
+               return frame_->audio_data();\r
+       }\r
+};\r
+\r
+struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback, boost::noncopyable\r
+{              \r
+       const int                                                       channel_index_;\r
+       const configuration                                     config_;\r
+\r
+       CComPtr<IDeckLink>                                      decklink_;\r
+       CComQIPtr<IDeckLinkOutput>                      output_;\r
+       CComQIPtr<IDeckLinkConfiguration>       configuration_;\r
+       CComQIPtr<IDeckLinkKeyer>                       keyer_;\r
+       CComQIPtr<IDeckLinkAttributes>          attributes_;\r
+\r
+       tbb::spin_mutex                                         exception_mutex_;\r
+       std::exception_ptr                                      exception_;\r
+\r
+       tbb::atomic<bool>                                       is_running_;\r
+               \r
+       const std::wstring                                      model_name_;\r
+       const core::video_format_desc           format_desc_;\r
+       const size_t                                            buffer_size_;\r
+\r
+       long long                                                       video_scheduled_;\r
+       long long                                                       audio_scheduled_;\r
+\r
+       size_t                                                          preroll_count_;\r
+               \r
+       boost::circular_buffer<std::vector<int32_t>>    audio_container_;\r
+\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> video_frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> audio_frame_buffer_;\r
+       \r
+       safe_ptr<diagnostics::graph> graph_;\r
+       boost::timer tick_timer_;\r
+       BMDReferenceStatus last_reference_status_;\r
+       retry_task<bool> send_completion_;\r
+\r
+public:\r
+       decklink_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index) \r
+               : channel_index_(channel_index)\r
+               , config_(config)\r
+               , decklink_(get_device(config.device_index))\r
+               , output_(decklink_)\r
+               , configuration_(decklink_)\r
+               , keyer_(decklink_)\r
+               , attributes_(decklink_)\r
+               , model_name_(get_model_name(decklink_))\r
+               , format_desc_(format_desc)\r
+               , buffer_size_(config.buffer_depth()) // Minimum buffer-size 3.\r
+               , video_scheduled_(0)\r
+               , audio_scheduled_(0)\r
+               , preroll_count_(0)\r
+               , audio_container_(buffer_size_+1)\r
+               , last_reference_status_(static_cast<BMDReferenceStatus>(-1))\r
+       {\r
+               is_running_ = true;\r
+                               \r
+               video_frame_buffer_.set_capacity(1);\r
+               audio_frame_buffer_.set_capacity(1);\r
+\r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+               graph_->set_color("flushed-frame", diagnostics::color(0.4f, 0.3f, 0.8f));\r
+               graph_->set_color("buffered-audio", diagnostics::color(0.9f, 0.9f, 0.5f));\r
+               graph_->set_color("buffered-video", diagnostics::color(0.2f, 0.9f, 0.9f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+               \r
+               enable_video(get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault));\r
+                               \r
+               if(config.embedded_audio)\r
+                       enable_audio();\r
+\r
+               set_latency(config.latency);                            \r
+               set_keyer(config.keyer);\r
+                               \r
+               if(config.embedded_audio)               \r
+                       output_->BeginAudioPreroll();           \r
+               \r
+               for(size_t n = 0; n < buffer_size_; ++n)\r
+                       schedule_next_video(make_safe<core::read_frame>());\r
+\r
+               if(!config.embedded_audio)\r
+                       start_playback();\r
+       }\r
+\r
+       ~decklink_consumer()\r
+       {               \r
+               is_running_ = false;\r
+               video_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
+               audio_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
+\r
+               if(output_ != nullptr) \r
+               {\r
+                       output_->StopScheduledPlayback(0, nullptr, 0);\r
+                       if(config_.embedded_audio)\r
+                               output_->DisableAudioOutput();\r
+                       output_->DisableVideoOutput();\r
+               }\r
+       }\r
+                       \r
+       void set_latency(configuration::latency_t latency)\r
+       {               \r
+               if(latency == configuration::low_latency)\r
+               {\r
+                       configuration_->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, true);\r
+                       CASPAR_LOG(info) << print() << L" Enabled low-latency mode.";\r
+               }\r
+               else if(latency == configuration::normal_latency)\r
+               {                       \r
+                       configuration_->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, false);\r
+                       CASPAR_LOG(info) << print() << L" Disabled low-latency mode.";\r
+               }\r
+       }\r
+\r
+       void set_keyer(configuration::keyer_t keyer)\r
+       {\r
+               if(keyer == configuration::internal_keyer) \r
+               {\r
+                       BOOL value = true;\r
+                       if(SUCCEEDED(attributes_->GetFlag(BMDDeckLinkSupportsInternalKeying, &value)) && !value)\r
+                               CASPAR_LOG(error) << print() << L" Failed to enable internal keyer.";   \r
+                       else if(FAILED(keyer_->Enable(FALSE)))                  \r
+                               CASPAR_LOG(error) << print() << L" Failed to enable internal keyer.";                   \r
+                       else if(FAILED(keyer_->SetLevel(255)))                  \r
+                               CASPAR_LOG(error) << print() << L" Failed to set key-level to max.";\r
+                       else\r
+                               CASPAR_LOG(info) << print() << L" Enabled internal keyer.";             \r
+               }\r
+               else if(keyer == configuration::external_keyer)\r
+               {\r
+                       BOOL value = true;\r
+                       if(SUCCEEDED(attributes_->GetFlag(BMDDeckLinkSupportsExternalKeying, &value)) && !value)\r
+                               CASPAR_LOG(error) << print() << L" Failed to enable external keyer.";   \r
+                       else if(FAILED(keyer_->Enable(TRUE)))                   \r
+                               CASPAR_LOG(error) << print() << L" Failed to enable external keyer.";   \r
+                       else if(FAILED(keyer_->SetLevel(255)))                  \r
+                               CASPAR_LOG(error) << print() << L" Failed to set key-level to max.";\r
+                       else\r
+                               CASPAR_LOG(info) << print() << L" Enabled external keyer.";                     \r
+               }\r
+       }\r
+       \r
+       void enable_audio()\r
+       {\r
+               if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, 2, bmdAudioOutputStreamTimestamped)))\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable audio output."));\r
+                               \r
+               if(FAILED(output_->SetAudioCallback(this)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not set audio callback."));\r
+\r
+               CASPAR_LOG(info) << print() << L" Enabled embedded-audio.";\r
+       }\r
+\r
+       void enable_video(BMDDisplayMode display_mode)\r
+       {\r
+               if(FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));\r
+               \r
+               if(FAILED(output_->SetScheduledFrameCompletionCallback(this)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() \r
+                                                                       << msg_info(narrow(print()) + " Failed to set playback completion callback.")\r
+                                                                       << boost::errinfo_api_function("SetScheduledFrameCompletionCallback"));\r
+       }\r
+\r
+       void start_playback()\r
+       {\r
+               if(FAILED(output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to schedule playback."));\r
+       }\r
+       \r
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))     {return E_NOINTERFACE;}\r
+       STDMETHOD_(ULONG, AddRef())                                     {return 1;}\r
+       STDMETHOD_(ULONG, Release())                            {return 1;}\r
+       \r
+       STDMETHOD(ScheduledPlaybackHasStopped())\r
+       {\r
+               is_running_ = false;\r
+               CASPAR_LOG(info) << print() << L" Scheduled playback has stopped.";\r
+               return S_OK;\r
+       }\r
+\r
+       STDMETHOD(ScheduledFrameCompleted(IDeckLinkVideoFrame* completed_frame, BMDOutputFrameCompletionResult result))\r
+       {\r
+               if(!is_running_)\r
+                       return E_FAIL;\r
+               \r
+               try\r
+               {\r
+                       if(result == bmdOutputFrameDisplayedLate)\r
+                       {\r
+                               graph_->set_tag("late-frame");\r
+                               video_scheduled_ += format_desc_.duration;\r
+                               audio_scheduled_ += reinterpret_cast<decklink_frame*>(completed_frame)->audio_data().size()/format_desc_.audio_channels;\r
+                               //++video_scheduled_;\r
+                               //audio_scheduled_ += format_desc_.audio_cadence[0];\r
+                               //++audio_scheduled_;\r
+                       }\r
+                       else if(result == bmdOutputFrameDropped)\r
+                               graph_->set_tag("dropped-frame");\r
+                       else if(result == bmdOutputFrameFlushed)\r
+                               graph_->set_tag("flushed-frame");\r
+\r
+                       std::shared_ptr<core::read_frame> frame;        \r
+                       video_frame_buffer_.pop(frame);\r
+                       send_completion_.try_completion();\r
+                       schedule_next_video(make_safe_ptr(frame));      \r
+                       \r
+                       unsigned long buffered;\r
+                       output_->GetBufferedVideoFrameCount(&buffered);\r
+                       graph_->set_value("buffered-video", static_cast<double>(buffered)/format_desc_.fps);\r
+               }\r
+               catch(...)\r
+               {\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       exception_ = std::current_exception();\r
+                       return E_FAIL;\r
+               }\r
+\r
+               return S_OK;\r
+       }\r
+               \r
+       STDMETHOD(RenderAudioSamples(BOOL preroll))\r
+       {\r
+               if(!is_running_)\r
+                       return E_FAIL;\r
+               \r
+               try\r
+               {       \r
+                       if(preroll)\r
+                       {\r
+                               if(++preroll_count_ >= buffer_size_)\r
+                               {\r
+                                       output_->EndAudioPreroll();\r
+                                       start_playback();                               \r
+                               }\r
+                               else\r
+                                       schedule_next_audio(core::audio_buffer(format_desc_.audio_cadence[preroll % format_desc_.audio_cadence.size()], 0));    \r
+                       }\r
+                       else\r
+                       {\r
+                               std::shared_ptr<core::read_frame> frame;\r
+                               audio_frame_buffer_.pop(frame);\r
+                               send_completion_.try_completion();\r
+                               schedule_next_audio(frame->audio_data());\r
+                       }\r
+\r
+                       unsigned long buffered;\r
+                       output_->GetBufferedAudioSampleFrameCount(&buffered);\r
+                       graph_->set_value("buffered-audio", static_cast<double>(buffered)/(format_desc_.audio_cadence[0]*2));\r
+               }\r
+               catch(...)\r
+               {\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       exception_ = std::current_exception();\r
+                       return E_FAIL;\r
+               }\r
+\r
+               return S_OK;\r
+       }\r
+\r
+       template<typename T>\r
+       void schedule_next_audio(const T& audio_data)\r
+       {\r
+               const int sample_frame_count = audio_data.size()/format_desc_.audio_channels;\r
+\r
+               audio_container_.push_back(std::vector<int32_t>(audio_data.begin(), audio_data.end()));\r
+\r
+               if(FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), sample_frame_count, audio_scheduled_, format_desc_.audio_sample_rate, nullptr)))\r
+                       CASPAR_LOG(error) << print() << L" Failed to schedule audio.";\r
+\r
+               audio_scheduled_ += sample_frame_count;\r
+       }\r
+                       \r
+       void schedule_next_video(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               CComPtr<IDeckLinkVideoFrame> frame2(new decklink_frame(frame, format_desc_, config_.key_only));\r
+               if(FAILED(output_->ScheduleVideoFrame(frame2, video_scheduled_, format_desc_.duration, format_desc_.time_scale)))\r
+                       CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
+\r
+               video_scheduled_ += format_desc_.duration;\r
+\r
+               graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
+               tick_timer_.restart();\r
+\r
+               detect_reference_signal_change();\r
+       }\r
+\r
+       void detect_reference_signal_change()\r
+       {\r
+               BMDReferenceStatus reference_status;\r
+\r
+               if (output_->GetReferenceStatus(&reference_status) != S_OK)\r
+               {\r
+                       CASPAR_LOG(error) << print() << L" Reference signal: failed while querying status";\r
+               }\r
+               else if (reference_status != last_reference_status_)\r
+               {\r
+                       last_reference_status_ = reference_status;\r
+\r
+                       if (reference_status == 0)\r
+                               CASPAR_LOG(info) << print() << L" Reference signal: not detected.";\r
+                       else if (reference_status & bmdReferenceNotSupportedByHardware)\r
+                               CASPAR_LOG(info) << print() << L" Reference signal: not supported by hardware.";\r
+                       else if (reference_status & bmdReferenceLocked)\r
+                               CASPAR_LOG(info) << print() << L" Reference signal: locked.";\r
+                       else\r
+                               CASPAR_LOG(info) << print() << L" Reference signal: Unhandled enum bitfield: " << reference_status;\r
+               }\r
+       }\r
+\r
+       boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               {\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       if(exception_ != nullptr)\r
+                               std::rethrow_exception(exception_);\r
+               }\r
+\r
+               if(!is_running_)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Is not running."));\r
+\r
+               bool audio_ready = !config_.embedded_audio;\r
+               bool video_ready = false;\r
+\r
+               auto enqueue_task = [audio_ready, video_ready, frame, this]() mutable -> boost::optional<bool>\r
+               {\r
+                       if (!audio_ready)\r
+                               audio_ready = audio_frame_buffer_.try_push(frame);\r
+\r
+                       if (!video_ready)\r
+                               video_ready = video_frame_buffer_.try_push(frame);\r
+\r
+                       if (audio_ready && video_ready)\r
+                               return true;\r
+                       else\r
+                               return boost::optional<bool>();\r
+               };\r
+               \r
+               if (enqueue_task())\r
+                       return wrap_as_future(true);\r
+\r
+               send_completion_.set_task(enqueue_task);\r
+\r
+               return send_completion_.get_future();\r
+       }\r
+       \r
+       std::wstring print() const\r
+       {\r
+               return model_name_ + L" [" + boost::lexical_cast<std::wstring>(channel_index_) + L"-" +\r
+                       boost::lexical_cast<std::wstring>(config_.device_index) + L"|" +  format_desc_.name + L"]";\r
+       }\r
+};\r
+\r
+struct decklink_consumer_proxy : public core::frame_consumer\r
+{\r
+       const configuration                             config_;\r
+       com_context<decklink_consumer>  context_;\r
+       std::vector<size_t>                             audio_cadence_;\r
+public:\r
+\r
+       decklink_consumer_proxy(const configuration& config)\r
+               : config_(config)\r
+               , context_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")\r
+       {\r
+       }\r
+\r
+       ~decklink_consumer_proxy()\r
+       {\r
+               if(context_)\r
+               {\r
+                       auto str = print();\r
+                       context_.reset();\r
+                       CASPAR_LOG(info) << str << L" Successfully Uninitialized.";     \r
+               }\r
+       }\r
+\r
+       // frame_consumer\r
+       \r
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               context_.reset([&]{return new decklink_consumer(config_, format_desc, channel_index);});                \r
+               audio_cadence_ = format_desc.audio_cadence;             \r
+\r
+               CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
+       }\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override\r
+       {\r
+               CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
+               boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+\r
+               return context_->send(frame);\r
+       }\r
+       \r
+       virtual std::wstring print() const override\r
+       {\r
+               return context_ ? context_->print() : L"[decklink_consumer]";\r
+       }               \r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"decklink-consumer");\r
+               info.add(L"key-only", config_.key_only);\r
+               info.add(L"device", config_.device_index);\r
+               info.add(L"low-latency", config_.low_latency);\r
+               info.add(L"embedded-audio", config_.embedded_audio);\r
+               info.add(L"low-latency", config_.low_latency);\r
+               //info.add(L"internal-key", config_.internal_key);\r
+               return info;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return config_.buffer_depth();\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 300 + config_.device_index;\r
+       }\r
+};     \r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params) \r
+{\r
+       if(params.size() < 1 || params[0] != L"DECKLINK")\r
+               return core::frame_consumer::empty();\r
+       \r
+       configuration config;\r
+               \r
+       if(params.size() > 1)\r
+               config.device_index = lexical_cast_or_default<int>(params[1], config.device_index);\r
+       \r
+       if(std::find(params.begin(), params.end(), L"INTERNAL_KEY")                     != params.end())\r
+               config.keyer = configuration::internal_keyer;\r
+       else if(std::find(params.begin(), params.end(), L"EXTERNAL_KEY")        != params.end())\r
+               config.keyer = configuration::external_keyer;\r
+       else\r
+               config.keyer = configuration::default_keyer;\r
+\r
+       if(std::find(params.begin(), params.end(), L"LOW_LATENCY")       != params.end())\r
+               config.latency = configuration::low_latency;\r
+\r
+       config.embedded_audio   = std::find(params.begin(), params.end(), L"EMBEDDED_AUDIO") != params.end();\r
+       config.key_only                 = std::find(params.begin(), params.end(), L"KEY_ONLY")           != params.end();\r
+\r
+       return make_safe<decklink_consumer_proxy>(config);\r
+}\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree) \r
+{\r
+       configuration config;\r
+\r
+       auto keyer = ptree.get(L"keyer", L"external");\r
+       if(keyer == L"external")\r
+               config.keyer = configuration::external_keyer;\r
+       else if(keyer == L"internal")\r
+               config.keyer = configuration::internal_keyer;\r
+\r
+       auto latency = ptree.get(L"latency", L"normal");\r
+       if(latency == L"low")\r
+               config.latency = configuration::low_latency;\r
+       else if(latency == L"normal")\r
+               config.latency = configuration::normal_latency;\r
+\r
+       config.key_only                         = ptree.get(L"key-only",                config.key_only);\r
+       config.device_index                     = ptree.get(L"device",                  config.device_index);\r
+       config.embedded_audio           = ptree.get(L"embedded-audio",  config.embedded_audio);\r
+       config.base_buffer_depth        = ptree.get(L"buffer-depth",    config.base_buffer_depth);\r
+\r
+       return make_safe<decklink_consumer_proxy>(config);\r
+}\r
+\r
+}}\r
+\r
+/*\r
+##############################################################################\r
+Pre-rolling\r
+\r
+Mail: 2011-05-09\r
+\r
+Yoshan\r
+BMD Developer Support\r
+developer@blackmagic-design.com\r
+\r
+-----------------------------------------------------------------------------\r
+\r
+Thanks for your inquiry. The minimum number of frames that you can preroll \r
+for scheduled playback is three frames for video and four frames for audio. \r
+As you mentioned if you preroll less frames then playback will not start or\r
+playback will be very sporadic. From our experience with Media Express, we \r
+recommended that at least seven frames are prerolled for smooth playback. \r
+\r
+Regarding the bmdDeckLinkConfigLowLatencyVideoOutput flag:\r
+There can be around 3 frames worth of latency on scheduled output.\r
+When the bmdDeckLinkConfigLowLatencyVideoOutput flag is used this latency is\r
+reduced  or removed for scheduled playback. If the DisplayVideoFrameSync() \r
+method is used, the bmdDeckLinkConfigLowLatencyVideoOutput setting will \r
+guarantee that the provided frame will be output as soon the previous \r
+frame output has been completed.\r
+################################################################################\r
+*/\r
+\r
+/*\r
+##############################################################################\r
+Async DMA Transfer without redundant copying\r
+\r
+Mail: 2011-05-10\r
+\r
+Yoshan\r
+BMD Developer Support\r
+developer@blackmagic-design.com\r
+\r
+-----------------------------------------------------------------------------\r
+\r
+Thanks for your inquiry. You could try subclassing IDeckLinkMutableVideoFrame \r
+and providing a pointer to your video buffer when GetBytes() is called. \r
+This may help to keep copying to a minimum. Please ensure that the pixel \r
+format is in bmdFormat10BitYUV, otherwise the DeckLink API / driver will \r
+have to colourspace convert which may result in additional copying.\r
+################################################################################\r
+*/
\ No newline at end of file
diff --git a/modules/decklink/consumer/decklink_consumer.h b/modules/decklink/consumer/decklink_consumer.h
new file mode 100644 (file)
index 0000000..02d9b18
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar {\r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+}\r
+\r
+namespace decklink {\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/decklink/decklink.cpp b/modules/decklink/decklink.cpp
new file mode 100644 (file)
index 0000000..b8c834e
--- /dev/null
@@ -0,0 +1,114 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"\r
+\r
+#include "decklink.h"\r
+#include "util/util.h"\r
+\r
+#include "consumer/decklink_consumer.h"\r
+#include "producer/decklink_producer.h"\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include "interop/DeckLinkAPI_h.h"\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable : 4996)\r
+\r
+       #include <atlbase.h>\r
+\r
+       #include <atlcom.h>\r
+       #include <atlhost.h>\r
+\r
+#pragma warning(push)\r
+\r
+namespace caspar { namespace decklink {\r
+\r
+void init()\r
+{\r
+       struct co_init\r
+       {\r
+               co_init(){::CoInitialize(nullptr);}\r
+               ~co_init(){::CoUninitialize();}\r
+       } init;\r
+       \r
+       CComPtr<IDeckLinkIterator> pDecklinkIterator;\r
+       if(FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))         \r
+               return;\r
+               \r
+       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+       core::register_producer_factory(create_producer);\r
+}\r
+\r
+std::wstring get_version() \r
+{\r
+       std::wstring version = L"Not found";\r
+       \r
+       struct co_init\r
+       {\r
+               co_init(){::CoInitialize(nullptr);}\r
+               ~co_init(){::CoUninitialize();}\r
+       } init;\r
+\r
+       try\r
+       {\r
+               CComPtr<IDeckLinkIterator> pDecklinkIterator;\r
+               if(SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))              \r
+                       version = get_version(pDecklinkIterator);\r
+       }\r
+       catch(...){}\r
+\r
+       return version;\r
+}\r
+\r
+std::vector<std::wstring> get_device_list()\r
+{\r
+       std::vector<std::wstring> devices;\r
+       \r
+       struct co_init\r
+       {\r
+               co_init(){::CoInitialize(nullptr);}\r
+               ~co_init(){::CoUninitialize();}\r
+       } init;\r
+\r
+       try\r
+       {\r
+               CComPtr<IDeckLinkIterator> pDecklinkIterator;\r
+               if(SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))\r
+               {               \r
+                       IDeckLink* decklink;\r
+                       for(int n = 1; pDecklinkIterator->Next(&decklink) == S_OK; ++n) \r
+                       {\r
+                               BSTR model_name = L"Unknown";\r
+                               decklink->GetModelName(&model_name);\r
+                               decklink->Release();\r
+                               devices.push_back(std::wstring(model_name) + L" [" + boost::lexical_cast<std::wstring>(n) + L"]");      \r
+                       }\r
+               }\r
+       }\r
+       catch(...){}\r
+\r
+       return devices;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/decklink/decklink.h b/modules/decklink/decklink.h
new file mode 100644 (file)
index 0000000..0dff05d
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace decklink {\r
+\r
+void init();\r
+\r
+std::wstring get_version();\r
+std::vector<std::wstring> get_device_list();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/decklink/decklink.vcxproj b/modules/decklink/decklink.vcxproj
new file mode 100644 (file)
index 0000000..39c5353
--- /dev/null
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{D3611658-8F54-43CF-B9AF-A5CF8C1102EA}</ProjectGuid>\r
+    <RootNamespace>decklink</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>decklink</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\decklink_consumer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="decklink.cpp" />\r
+    <ClCompile Include="interop\DeckLinkAPI_i.c">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\decklink_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\decklink_consumer.h" />\r
+    <ClInclude Include="decklink.h" />\r
+    <ClInclude Include="interop\DeckLinkAPIVersion.h" />\r
+    <ClInclude Include="interop\DeckLinkAPI_h.h" />\r
+    <ClInclude Include="producer\decklink_producer.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\util.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\DeckLinkAPI.idl">\r
+      <OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">interop\</OutputDirectory>\r
+      <OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">interop\</OutputDirectory>\r
+      <OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">interop\</OutputDirectory>\r
+      <OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">interop\</OutputDirectory>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI_v7_1.idl">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI_v7_3.idl">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI_v7_6.idl">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </Midl>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\ffmpeg\ffmpeg.vcxproj">\r
+      <Project>{f6223af3-be0b-4b61-8406-98922ce521c2}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/decklink/decklink.vcxproj.filters b/modules/decklink/decklink.vcxproj.filters
new file mode 100644 (file)
index 0000000..7a7b1d7
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{e4ed0331-a111-453e-9249-9f3ee3277f4d}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\util">\r
+      <UniqueIdentifier>{963cca43-0294-4fdd-a786-b98499c22644}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{d1c2b767-8787-4ba5-b141-0c17d030bfe0}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\interop">\r
+      <UniqueIdentifier>{8f268fa2-b236-4cb5-86dc-ca6612b251a5}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{681577c3-a264-4849-bdef-27fc1988e50f}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\decklink_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\decklink_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="interop\DeckLinkAPI_i.c">\r
+      <Filter>source\interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="decklink.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\decklink_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\decklink_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\util.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\DeckLinkAPIVersion.h">\r
+      <Filter>source\interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\DeckLinkAPI_h.h">\r
+      <Filter>source\interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="decklink.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\DeckLinkAPI_v7_1.idl">\r
+      <Filter>source\interop</Filter>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI_v7_3.idl">\r
+      <Filter>source\interop</Filter>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI_v7_6.idl">\r
+      <Filter>source\interop</Filter>\r
+    </Midl>\r
+    <Midl Include="interop\DeckLinkAPI.idl">\r
+      <Filter>source\interop</Filter>\r
+    </Midl>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/decklink/interop/DeckLinkAPI.idl b/modules/decklink/interop/DeckLinkAPI.idl
new file mode 100644 (file)
index 0000000..abe5247
--- /dev/null
@@ -0,0 +1,1159 @@
+/* -LICENSE-START-\r
+** Copyright (c) 2011 Blackmagic Design\r
+**\r
+** Permission is hereby granted, free of charge, to any person or organization\r
+** obtaining a copy of the software and accompanying documentation covered by\r
+** this license (the "Software") to use, reproduce, display, distribute,\r
+** execute, and transmit the Software, and to prepare derivative works of the\r
+** Software, and to permit third-parties to whom the Software is furnished to\r
+** do so, all subject to the following:\r
+** \r
+** The copyright notices in the Software and this entire statement, including\r
+** the above license grant, this restriction and the following disclaimer,\r
+** must be included in all copies of the Software, in whole or in part, and\r
+** all derivative works of the Software, unless such copies or derivative\r
+** works are solely in the form of machine-executable object code generated by\r
+** a source language processor.\r
+** \r
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\r
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\r
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\r
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+** DEALINGS IN THE SOFTWARE.\r
+** -LICENSE-END-\r
+*/\r
+\r
+/* DeckLinkAPI.idl */\r
+\r
+import "unknwn.idl";\r
+\r
+[uuid(D864517A-EDD5-466D-867D-C819F1C052BB),\r
+version(1.0), helpstring("DeckLink API Library")]\r
+library DeckLinkAPI\r
+{\r
+\r
+// Type Declarations\r
+\r
+typedef LONGLONG BMDTimeValue;\r
+typedef LONGLONG BMDTimeScale;\r
+typedef unsigned long BMDTimecodeBCD;\r
+typedef unsigned long BMDTimecodeUserBits;\r
+\r
+\r
+// Enumeration Mapping\r
+\r
+cpp_quote("typedef unsigned long BMDDisplayModeFlags;")\r
+cpp_quote("typedef unsigned long BMDFrameFlags;")\r
+cpp_quote("typedef unsigned long BMDVideoInputFlags;")\r
+cpp_quote("typedef unsigned long BMDVideoInputFormatChangedEvents;")\r
+cpp_quote("typedef unsigned long BMDDetectedVideoInputFormatFlags;")\r
+cpp_quote("typedef unsigned long BMDTimecodeFlags;")\r
+cpp_quote("typedef unsigned long BMDAnalogVideoFlags;")\r
+cpp_quote("typedef unsigned long BMDDeckControlStatusFlags;")\r
+cpp_quote("typedef unsigned long BMDDeckControlExportModeOpsFlags;")\r
+cpp_quote("#if 0")\r
+typedef enum _BMDDisplayModeFlags BMDDisplayModeFlags;\r
+typedef enum _BMDFrameFlags BMDFrameFlags;\r
+typedef enum _BMDVideoInputFlags BMDVideoInputFlags;\r
+typedef enum _BMDVideoInputFormatChangedEvents BMDVideoInputFormatChangedEvents;\r
+typedef enum _BMDDetectedVideoInputFormatFlags BMDDetectedVideoInputFormatFlags;\r
+typedef enum _BMDTimecodeFlags BMDTimecodeFlags;\r
+typedef enum _BMDAnalogVideoFlags BMDAnalogVideoFlags;\r
+typedef enum _BMDDeckControlStatusFlags BMDDeckControlStatusFlags;\r
+typedef enum _BMDDeckControlExportModeOpsFlags BMDDeckControlExportModeOpsFlags;\r
+cpp_quote("#endif")\r
+\r
+\r
+/* Enum BMDDisplayMode - Video display modes */\r
+\r
+typedef [v1_enum] enum _BMDDisplayMode {\r
+\r
+    /* SD Modes */\r
+\r
+    bmdModeNTSC                                        = /* 'ntsc' */ 0x6E747363,\r
+    bmdModeNTSC2398                                    = /* 'nt23' */ 0x6E743233,      // 3:2 pulldown\r
+    bmdModePAL                                         = /* 'pal ' */ 0x70616C20,\r
+    bmdModeNTSCp                                       = /* 'ntsp' */ 0x6E747370,\r
+    bmdModePALp                                        = /* 'palp' */ 0x70616C70,\r
+\r
+    /* HD 1080 Modes */\r
+\r
+    bmdModeHD1080p2398                                 = /* '23ps' */ 0x32337073,\r
+    bmdModeHD1080p24                                   = /* '24ps' */ 0x32347073,\r
+    bmdModeHD1080p25                                   = /* 'Hp25' */ 0x48703235,\r
+    bmdModeHD1080p2997                                 = /* 'Hp29' */ 0x48703239,\r
+    bmdModeHD1080p30                                   = /* 'Hp30' */ 0x48703330,\r
+    bmdModeHD1080i50                                   = /* 'Hi50' */ 0x48693530,\r
+    bmdModeHD1080i5994                                 = /* 'Hi59' */ 0x48693539,\r
+    bmdModeHD1080i6000                                 = /* 'Hi60' */ 0x48693630,      // N.B. This _really_ is 60.00 Hz.\r
+    bmdModeHD1080p50                                   = /* 'Hp50' */ 0x48703530,\r
+    bmdModeHD1080p5994                                 = /* 'Hp59' */ 0x48703539,\r
+    bmdModeHD1080p6000                                 = /* 'Hp60' */ 0x48703630,      // N.B. This _really_ is 60.00 Hz.\r
+\r
+    /* HD 720 Modes */\r
+\r
+    bmdModeHD720p50                                    = /* 'hp50' */ 0x68703530,\r
+    bmdModeHD720p5994                                  = /* 'hp59' */ 0x68703539,\r
+    bmdModeHD720p60                                    = /* 'hp60' */ 0x68703630,\r
+\r
+    /* 2k Modes */\r
+\r
+    bmdMode2k2398                                      = /* '2k23' */ 0x326B3233,\r
+    bmdMode2k24                                        = /* '2k24' */ 0x326B3234,\r
+    bmdMode2k25                                        = /* '2k25' */ 0x326B3235\r
+} BMDDisplayMode;\r
+\r
+\r
+/* Enum BMDFieldDominance - Video field dominance */\r
+\r
+typedef [v1_enum] enum _BMDFieldDominance {\r
+    bmdUnknownFieldDominance                           = 0,\r
+    bmdLowerFieldFirst                                 = /* 'lowr' */ 0x6C6F7772,\r
+    bmdUpperFieldFirst                                 = /* 'uppr' */ 0x75707072,\r
+    bmdProgressiveFrame                                = /* 'prog' */ 0x70726F67,\r
+    bmdProgressiveSegmentedFrame                       = /* 'psf ' */ 0x70736620\r
+} BMDFieldDominance;\r
+\r
+\r
+/* Enum BMDPixelFormat - Video pixel formats supported for output/input */\r
+\r
+typedef [v1_enum] enum _BMDPixelFormat {\r
+    bmdFormat8BitYUV                                   = /* '2vuy' */ 0x32767579,\r
+    bmdFormat10BitYUV                                  = /* 'v210' */ 0x76323130,\r
+    bmdFormat8BitARGB                                  = 32,\r
+    bmdFormat8BitBGRA                                  = /* 'BGRA' */ 0x42475241,\r
+    bmdFormat10BitRGB                                  = /* 'r210' */ 0x72323130       // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10\r
+} BMDPixelFormat;\r
+\r
+\r
+/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */\r
+\r
+[v1_enum] enum _BMDDisplayModeFlags {\r
+    bmdDisplayModeSupports3D                           = 1 << 0,\r
+    bmdDisplayModeColorspaceRec601                     = 1 << 1,\r
+    bmdDisplayModeColorspaceRec709                     = 1 << 2\r
+};\r
+\r
+\r
+/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */\r
+\r
+typedef [v1_enum] enum _BMDVideoOutputFlags {\r
+    bmdVideoOutputFlagDefault                          = 0,\r
+    bmdVideoOutputVANC                                 = 1 << 0,\r
+    bmdVideoOutputVITC                                 = 1 << 1,\r
+    bmdVideoOutputRP188                                = 1 << 2,\r
+    bmdVideoOutputDualStream3D                         = 1 << 4\r
+} BMDVideoOutputFlags;\r
+\r
+\r
+/* Enum BMDFrameFlags - Frame flags */\r
+\r
+[v1_enum] enum _BMDFrameFlags {\r
+    bmdFrameFlagDefault                                = 0,\r
+    bmdFrameFlagFlipVertical                           = 1 << 0,\r
+\r
+    /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */\r
+\r
+    bmdFrameHasNoInputSource                           = 1 << 31\r
+};\r
+\r
+\r
+/* Enum BMDVideoInputFlags - Flags applicable to video input */\r
+\r
+[v1_enum] enum _BMDVideoInputFlags {\r
+    bmdVideoInputFlagDefault                           = 0,\r
+    bmdVideoInputEnableFormatDetection                 = 1 << 0,\r
+    bmdVideoInputDualStream3D                          = 1 << 1\r
+};\r
+\r
+\r
+/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */\r
+\r
+[v1_enum] enum _BMDVideoInputFormatChangedEvents {\r
+    bmdVideoInputDisplayModeChanged                    = 1 << 0,\r
+    bmdVideoInputFieldDominanceChanged                 = 1 << 1,\r
+    bmdVideoInputColorspaceChanged                     = 1 << 2\r
+};\r
+\r
+\r
+/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */\r
+\r
+[v1_enum] enum _BMDDetectedVideoInputFormatFlags {\r
+    bmdDetectedVideoInputYCbCr422                      = 1 << 0,\r
+    bmdDetectedVideoInputRGB444                        = 1 << 1\r
+};\r
+\r
+\r
+/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */\r
+\r
+typedef [v1_enum] enum _BMDOutputFrameCompletionResult {\r
+    bmdOutputFrameCompleted,                          \r
+    bmdOutputFrameDisplayedLate,                      \r
+    bmdOutputFrameDropped,                            \r
+    bmdOutputFrameFlushed                             \r
+} BMDOutputFrameCompletionResult;\r
+\r
+\r
+/* Enum BMDReferenceStatus - GenLock input status */\r
+\r
+typedef [v1_enum] enum _BMDReferenceStatus {\r
+    bmdReferenceNotSupportedByHardware                 = 1 << 0,\r
+    bmdReferenceLocked                                 = 1 << 1\r
+} BMDReferenceStatus;\r
+\r
+\r
+/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */\r
+\r
+typedef [v1_enum] enum _BMDAudioSampleRate {\r
+    bmdAudioSampleRate48kHz                            = 48000\r
+} BMDAudioSampleRate;\r
+\r
+\r
+/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */\r
+\r
+typedef [v1_enum] enum _BMDAudioSampleType {\r
+    bmdAudioSampleType16bitInteger                     = 16,\r
+    bmdAudioSampleType32bitInteger                     = 32\r
+} BMDAudioSampleType;\r
+\r
+\r
+/* Enum BMDAudioOutputStreamType - Audio output stream type */\r
+\r
+typedef [v1_enum] enum _BMDAudioOutputStreamType {\r
+    bmdAudioOutputStreamContinuous,                   \r
+    bmdAudioOutputStreamContinuousDontResample,       \r
+    bmdAudioOutputStreamTimestamped                   \r
+} BMDAudioOutputStreamType;\r
+\r
+\r
+/* Enum BMDDisplayModeSupport - Output mode supported flags */\r
+\r
+typedef [v1_enum] enum _BMDDisplayModeSupport {\r
+    bmdDisplayModeNotSupported                         = 0,\r
+    bmdDisplayModeSupported,                          \r
+    bmdDisplayModeSupportedWithConversion             \r
+} BMDDisplayModeSupport;\r
+\r
+\r
+/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */\r
+\r
+typedef [v1_enum] enum _BMDTimecodeFormat {\r
+    bmdTimecodeRP188                                   = /* 'rp18' */ 0x72703138,\r
+    bmdTimecodeRP188Field2                             = /* 'rp12' */ 0x72703132,\r
+    bmdTimecodeVITC                                    = /* 'vitc' */ 0x76697463,\r
+    bmdTimecodeVITCField2                              = /* 'vit2' */ 0x76697432,\r
+    bmdTimecodeSerial                                  = /* 'seri' */ 0x73657269\r
+} BMDTimecodeFormat;\r
+\r
+\r
+/* Enum BMDTimecodeFlags - Timecode flags */\r
+\r
+[v1_enum] enum _BMDTimecodeFlags {\r
+    bmdTimecodeFlagDefault                             = 0,\r
+    bmdTimecodeIsDropFrame                             = 1 << 0\r
+};\r
+\r
+\r
+/* Enum BMDVideoConnection - Video connection types */\r
+\r
+typedef [v1_enum] enum _BMDVideoConnection {\r
+    bmdVideoConnectionSDI                              = 1 << 0,\r
+    bmdVideoConnectionHDMI                             = 1 << 1,\r
+    bmdVideoConnectionOpticalSDI                       = 1 << 2,\r
+    bmdVideoConnectionComponent                        = 1 << 3,\r
+    bmdVideoConnectionComposite                        = 1 << 4,\r
+    bmdVideoConnectionSVideo                           = 1 << 5\r
+} BMDVideoConnection;\r
+\r
+\r
+/* Enum BMDAnalogVideoFlags - Analog video display flags */\r
+\r
+[v1_enum] enum _BMDAnalogVideoFlags {\r
+    bmdAnalogVideoFlagCompositeSetup75                 = 1 << 0,\r
+    bmdAnalogVideoFlagComponentBetacamLevels           = 1 << 1\r
+};\r
+\r
+\r
+/* Enum BMDAudioConnection - Audio connection types */\r
+\r
+typedef [v1_enum] enum _BMDAudioConnection {\r
+    bmdAudioConnectionEmbedded                         = /* 'embd' */ 0x656D6264,\r
+    bmdAudioConnectionAESEBU                           = /* 'aes ' */ 0x61657320,\r
+    bmdAudioConnectionAnalog                           = /* 'anlg' */ 0x616E6C67\r
+} BMDAudioConnection;\r
+\r
+\r
+/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */\r
+\r
+typedef [v1_enum] enum _BMDAudioOutputAnalogAESSwitch {\r
+    bmdAudioOutputSwitchAESEBU                         = /* 'aes ' */ 0x61657320,\r
+    bmdAudioOutputSwitchAnalog                         = /* 'anlg' */ 0x616E6C67\r
+} BMDAudioOutputAnalogAESSwitch;\r
+\r
+\r
+/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */\r
+\r
+typedef [v1_enum] enum _BMDVideoOutputConversionMode {\r
+    bmdNoVideoOutputConversion                         = /* 'none' */ 0x6E6F6E65,\r
+    bmdVideoOutputLetterboxDownconversion              = /* 'ltbx' */ 0x6C746278,\r
+    bmdVideoOutputAnamorphicDownconversion             = /* 'amph' */ 0x616D7068,\r
+    bmdVideoOutputHD720toHD1080Conversion              = /* '720c' */ 0x37323063,\r
+    bmdVideoOutputHardwareLetterboxDownconversion      = /* 'HWlb' */ 0x48576C62,\r
+    bmdVideoOutputHardwareAnamorphicDownconversion     = /* 'HWam' */ 0x4857616D,\r
+    bmdVideoOutputHardwareCenterCutDownconversion      = /* 'HWcc' */ 0x48576363,\r
+    bmdVideoOutputHardware720p1080pCrossconversion     = /* 'xcap' */ 0x78636170,\r
+    bmdVideoOutputHardwareAnamorphic720pUpconversion   = /* 'ua7p' */ 0x75613770,\r
+    bmdVideoOutputHardwareAnamorphic1080iUpconversion  = /* 'ua1i' */ 0x75613169,\r
+    bmdVideoOutputHardwareAnamorphic149To720pUpconversion = /* 'u47p' */ 0x75343770,\r
+    bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = /* 'u41i' */ 0x75343169,\r
+    bmdVideoOutputHardwarePillarbox720pUpconversion    = /* 'up7p' */ 0x75703770,\r
+    bmdVideoOutputHardwarePillarbox1080iUpconversion   = /* 'up1i' */ 0x75703169\r
+} BMDVideoOutputConversionMode;\r
+\r
+\r
+/* Enum BMDVideoInputConversionMode - Video input conversion mode */\r
+\r
+typedef [v1_enum] enum _BMDVideoInputConversionMode {\r
+    bmdNoVideoInputConversion                          = /* 'none' */ 0x6E6F6E65,\r
+    bmdVideoInputLetterboxDownconversionFromHD1080     = /* '10lb' */ 0x31306C62,\r
+    bmdVideoInputAnamorphicDownconversionFromHD1080    = /* '10am' */ 0x3130616D,\r
+    bmdVideoInputLetterboxDownconversionFromHD720      = /* '72lb' */ 0x37326C62,\r
+    bmdVideoInputAnamorphicDownconversionFromHD720     = /* '72am' */ 0x3732616D,\r
+    bmdVideoInputLetterboxUpconversion                 = /* 'lbup' */ 0x6C627570,\r
+    bmdVideoInputAnamorphicUpconversion                = /* 'amup' */ 0x616D7570\r
+} BMDVideoInputConversionMode;\r
+\r
+\r
+/* Enum BMDVideo3DPackingFormat - Video 3D packing format */\r
+\r
+typedef [v1_enum] enum _BMDVideo3DPackingFormat {\r
+    bmdVideo3DPackingSidebySideHalf                    = /* 'sbsh' */ 0x73627368,\r
+    bmdVideo3DPackingLinebyLine                        = /* 'lbyl' */ 0x6C62796C,\r
+    bmdVideo3DPackingTopAndBottom                      = /* 'tabo' */ 0x7461626F,\r
+    bmdVideo3DPackingFramePacking                      = /* 'frpk' */ 0x6672706B,\r
+    bmdVideo3DPackingLeftOnly                          = /* 'left' */ 0x6C656674,\r
+    bmdVideo3DPackingRightOnly                         = /* 'righ' */ 0x72696768\r
+} BMDVideo3DPackingFormat;\r
+\r
+\r
+/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */\r
+\r
+typedef [v1_enum] enum _BMDIdleVideoOutputOperation {\r
+    bmdIdleVideoOutputBlack                            = /* 'blac' */ 0x626C6163,\r
+    bmdIdleVideoOutputLastFrame                        = /* 'lafa' */ 0x6C616661\r
+} BMDIdleVideoOutputOperation;\r
+\r
+\r
+/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */\r
+\r
+typedef [v1_enum] enum _BMDDeckLinkConfigurationID {\r
+\r
+    /* Serial port Flags */\r
+\r
+    bmdDeckLinkConfigSwapSerialRxTx                    = /* 'ssrt' */ 0x73737274,\r
+\r
+    /* Video Input/Output Flags */\r
+\r
+    bmdDeckLinkConfigUse1080pNotPsF                    = /* 'fpro' */ 0x6670726F,\r
+\r
+    /* Video Input/Output Integers */\r
+\r
+    bmdDeckLinkConfigHDMI3DPackingFormat               = /* '3dpf' */ 0x33647066,\r
+    bmdDeckLinkConfigBypass                            = /* 'byps' */ 0x62797073,\r
+\r
+    /* Audio Input/Output Flags */\r
+\r
+    bmdDeckLinkConfigAnalogAudioConsumerLevels         = /* 'aacl' */ 0x6161636C,\r
+\r
+    /* Video output flags */\r
+\r
+    bmdDeckLinkConfigFieldFlickerRemoval               = /* 'fdfr' */ 0x66646672,\r
+    bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion  = /* 'to59' */ 0x746F3539,\r
+    bmdDeckLinkConfig444SDIVideoOutput                 = /* '444o' */ 0x3434346F,\r
+    bmdDeckLinkConfig3GBpsVideoOutput                  = /* '3gbs' */ 0x33676273,\r
+    bmdDeckLinkConfigBlackVideoOutputDuringCapture     = /* 'bvoc' */ 0x62766F63,\r
+    bmdDeckLinkConfigLowLatencyVideoOutput             = /* 'llvo' */ 0x6C6C766F,\r
+\r
+    /* Video Output Integers */\r
+\r
+    bmdDeckLinkConfigVideoOutputConnection             = /* 'vocn' */ 0x766F636E,\r
+    bmdDeckLinkConfigVideoOutputConversionMode         = /* 'vocm' */ 0x766F636D,\r
+    bmdDeckLinkConfigAnalogVideoOutputFlags            = /* 'avof' */ 0x61766F66,\r
+    bmdDeckLinkConfigReferenceInputTimingOffset        = /* 'glot' */ 0x676C6F74,\r
+    bmdDeckLinkConfigVideoOutputIdleOperation          = /* 'voio' */ 0x766F696F,\r
+\r
+    /* Video Output Floats */\r
+\r
+    bmdDeckLinkConfigVideoOutputComponentLumaGain      = /* 'oclg' */ 0x6F636C67,\r
+    bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = /* 'occb' */ 0x6F636362,\r
+    bmdDeckLinkConfigVideoOutputComponentChromaRedGain = /* 'occr' */ 0x6F636372,\r
+    bmdDeckLinkConfigVideoOutputCompositeLumaGain      = /* 'oilg' */ 0x6F696C67,\r
+    bmdDeckLinkConfigVideoOutputCompositeChromaGain    = /* 'oicg' */ 0x6F696367,\r
+    bmdDeckLinkConfigVideoOutputSVideoLumaGain         = /* 'oslg' */ 0x6F736C67,\r
+    bmdDeckLinkConfigVideoOutputSVideoChromaGain       = /* 'oscg' */ 0x6F736367,\r
+\r
+    /* Video Input Integers */\r
+\r
+    bmdDeckLinkConfigVideoInputConnection              = /* 'vicn' */ 0x7669636E,\r
+    bmdDeckLinkConfigAnalogVideoInputFlags             = /* 'avif' */ 0x61766966,\r
+    bmdDeckLinkConfigVideoInputConversionMode          = /* 'vicm' */ 0x7669636D,\r
+    bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = /* 'pdif' */ 0x70646966,\r
+    bmdDeckLinkConfigVANCSourceLine1Mapping            = /* 'vsl1' */ 0x76736C31,\r
+    bmdDeckLinkConfigVANCSourceLine2Mapping            = /* 'vsl2' */ 0x76736C32,\r
+    bmdDeckLinkConfigVANCSourceLine3Mapping            = /* 'vsl3' */ 0x76736C33,\r
+\r
+    /* Video Input Floats */\r
+\r
+    bmdDeckLinkConfigVideoInputComponentLumaGain       = /* 'iclg' */ 0x69636C67,\r
+    bmdDeckLinkConfigVideoInputComponentChromaBlueGain = /* 'iccb' */ 0x69636362,\r
+    bmdDeckLinkConfigVideoInputComponentChromaRedGain  = /* 'iccr' */ 0x69636372,\r
+    bmdDeckLinkConfigVideoInputCompositeLumaGain       = /* 'iilg' */ 0x69696C67,\r
+    bmdDeckLinkConfigVideoInputCompositeChromaGain     = /* 'iicg' */ 0x69696367,\r
+    bmdDeckLinkConfigVideoInputSVideoLumaGain          = /* 'islg' */ 0x69736C67,\r
+    bmdDeckLinkConfigVideoInputSVideoChromaGain        = /* 'iscg' */ 0x69736367,\r
+\r
+    /* Audio Input Integers */\r
+\r
+    bmdDeckLinkConfigAudioInputConnection              = /* 'aicn' */ 0x6169636E,\r
+\r
+    /* Audio Input Floats */\r
+\r
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel1     = /* 'ais1' */ 0x61697331,\r
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel2     = /* 'ais2' */ 0x61697332,\r
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel3     = /* 'ais3' */ 0x61697333,\r
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel4     = /* 'ais4' */ 0x61697334,\r
+    bmdDeckLinkConfigDigitalAudioInputScale            = /* 'dais' */ 0x64616973,\r
+\r
+    /* Audio Output Integers */\r
+\r
+    bmdDeckLinkConfigAudioOutputAESAnalogSwitch        = /* 'aoaa' */ 0x616F6161,\r
+\r
+    /* Audio Output Floats */\r
+\r
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel1    = /* 'aos1' */ 0x616F7331,\r
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel2    = /* 'aos2' */ 0x616F7332,\r
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel3    = /* 'aos3' */ 0x616F7333,\r
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel4    = /* 'aos4' */ 0x616F7334,\r
+    bmdDeckLinkConfigDigitalAudioOutputScale           = /* 'daos' */ 0x64616F73\r
+} BMDDeckLinkConfigurationID;\r
+\r
+\r
+/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */\r
+\r
+typedef [v1_enum] enum _BMDDeckLinkAttributeID {\r
+\r
+    /* Flags */\r
+\r
+    BMDDeckLinkSupportsInternalKeying                  = /* 'keyi' */ 0x6B657969,\r
+    BMDDeckLinkSupportsExternalKeying                  = /* 'keye' */ 0x6B657965,\r
+    BMDDeckLinkSupportsHDKeying                        = /* 'keyh' */ 0x6B657968,\r
+    BMDDeckLinkSupportsInputFormatDetection            = /* 'infd' */ 0x696E6664,\r
+    BMDDeckLinkHasReferenceInput                       = /* 'hrin' */ 0x6872696E,\r
+    BMDDeckLinkHasSerialPort                           = /* 'hspt' */ 0x68737074,\r
+    BMDDeckLinkHasAnalogVideoOutputGain                = /* 'avog' */ 0x61766F67,\r
+    BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain     = /* 'ovog' */ 0x6F766F67,\r
+    BMDDeckLinkHasVideoInputAntiAliasingFilter         = /* 'aafl' */ 0x6161666C,\r
+    BMDDeckLinkHasBypass                               = /* 'byps' */ 0x62797073,\r
+\r
+    /* Integers */\r
+\r
+    BMDDeckLinkMaximumAudioChannels                    = /* 'mach' */ 0x6D616368,\r
+    BMDDeckLinkNumberOfSubDevices                      = /* 'nsbd' */ 0x6E736264,\r
+    BMDDeckLinkSubDeviceIndex                          = /* 'subi' */ 0x73756269,\r
+    BMDDeckLinkVideoOutputConnections                  = /* 'vocn' */ 0x766F636E,\r
+    BMDDeckLinkVideoInputConnections                   = /* 'vicn' */ 0x7669636E,\r
+\r
+    /* Floats */\r
+\r
+    BMDDeckLinkVideoInputGainMinimum                   = /* 'vigm' */ 0x7669676D,\r
+    BMDDeckLinkVideoInputGainMaximum                   = /* 'vigx' */ 0x76696778,\r
+    BMDDeckLinkVideoOutputGainMinimum                  = /* 'vogm' */ 0x766F676D,\r
+    BMDDeckLinkVideoOutputGainMaximum                  = /* 'vogx' */ 0x766F6778,\r
+\r
+    /* Strings */\r
+\r
+    BMDDeckLinkSerialPortDeviceName                    = /* 'slpn' */ 0x736C706E\r
+} BMDDeckLinkAttributeID;\r
+\r
+\r
+/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */\r
+\r
+typedef [v1_enum] enum _BMDDeckLinkAPIInformationID {\r
+    BMDDeckLinkAPIVersion                              = /* 'vers' */ 0x76657273\r
+} BMDDeckLinkAPIInformationID;\r
+\r
+\r
+/* Enum BMDDeckControlMode - DeckControl mode */\r
+\r
+typedef [v1_enum] enum _BMDDeckControlMode {\r
+    bmdDeckControlNotOpened                            = /* 'ntop' */ 0x6E746F70,\r
+    bmdDeckControlVTRControlMode                       = /* 'vtrc' */ 0x76747263,\r
+    bmdDeckControlExportMode                           = /* 'expm' */ 0x6578706D,\r
+    bmdDeckControlCaptureMode                          = /* 'capm' */ 0x6361706D\r
+} BMDDeckControlMode;\r
+\r
+\r
+/* Enum BMDDeckControlEvent - DeckControl event */\r
+\r
+typedef [v1_enum] enum _BMDDeckControlEvent {\r
+    bmdDeckControlAbortedEvent                         = /* 'abte' */ 0x61627465,      // This event is triggered when a capture or edit-to-tape operation is aborted.\r
+\r
+    /* Export-To-Tape events */\r
+\r
+    bmdDeckControlPrepareForExportEvent                = /* 'pfee' */ 0x70666565,      // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback() should be called at this point.\r
+    bmdDeckControlExportCompleteEvent                  = /* 'exce' */ 0x65786365,      // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback.\r
+\r
+    /* Capture events */\r
+\r
+    bmdDeckControlPrepareForCaptureEvent               = /* 'pfce' */ 0x70666365,      // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid.\r
+    bmdDeckControlCaptureCompleteEvent                 = /* 'ccev' */ 0x63636576       // This event is triggered a few frames after reaching the out-point.\r
+} BMDDeckControlEvent;\r
+\r
+\r
+/* Enum BMDDeckControlVTRControlState - VTR Control state */\r
+\r
+typedef [v1_enum] enum _BMDDeckControlVTRControlState {\r
+    bmdDeckControlNotInVTRControlMode                  = /* 'nvcm' */ 0x6E76636D,\r
+    bmdDeckControlVTRControlPlaying                    = /* 'vtrp' */ 0x76747270,\r
+    bmdDeckControlVTRControlRecording                  = /* 'vtrr' */ 0x76747272,\r
+    bmdDeckControlVTRControlStill                      = /* 'vtra' */ 0x76747261,\r
+    bmdDeckControlVTRControlSeeking                    = /* 'vtrs' */ 0x76747273,\r
+    bmdDeckControlVTRControlStopped                    = /* 'vtro' */ 0x7674726F\r
+} BMDDeckControlVTRControlState;\r
+\r
+\r
+/* Enum BMDDeckControlStatusFlags - Deck Control status flags */\r
+\r
+[v1_enum] enum _BMDDeckControlStatusFlags {\r
+    bmdDeckControlStatusDeckConnected                  = 1 << 0,\r
+    bmdDeckControlStatusRemoteMode                     = 1 << 1,\r
+    bmdDeckControlStatusRecordInhibited                = 1 << 2,\r
+    bmdDeckControlStatusCassetteOut                    = 1 << 3\r
+};\r
+\r
+\r
+/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */\r
+\r
+[v1_enum] enum _BMDDeckControlExportModeOpsFlags {\r
+    bmdDeckControlExportModeInsertVideo                = 1 << 0,\r
+    bmdDeckControlExportModeInsertAudio1               = 1 << 1,\r
+    bmdDeckControlExportModeInsertAudio2               = 1 << 2,\r
+    bmdDeckControlExportModeInsertAudio3               = 1 << 3,\r
+    bmdDeckControlExportModeInsertAudio4               = 1 << 4,\r
+    bmdDeckControlExportModeInsertAudio5               = 1 << 5,\r
+    bmdDeckControlExportModeInsertAudio6               = 1 << 6,\r
+    bmdDeckControlExportModeInsertAudio7               = 1 << 7,\r
+    bmdDeckControlExportModeInsertAudio8               = 1 << 8,\r
+    bmdDeckControlExportModeInsertAudio9               = 1 << 9,\r
+    bmdDeckControlExportModeInsertAudio10              = 1 << 10,\r
+    bmdDeckControlExportModeInsertAudio11              = 1 << 11,\r
+    bmdDeckControlExportModeInsertAudio12              = 1 << 12,\r
+    bmdDeckControlExportModeInsertTimeCode             = 1 << 13,\r
+    bmdDeckControlExportModeInsertAssemble             = 1 << 14,\r
+    bmdDeckControlExportModeInsertPreview              = 1 << 15,\r
+    bmdDeckControlUseManualExport                      = 1 << 16\r
+};\r
+\r
+\r
+/* Enum BMDDeckControlError - Deck Control error */\r
+\r
+typedef [v1_enum] enum _BMDDeckControlError {\r
+    bmdDeckControlNoError                              = /* 'noer' */ 0x6E6F6572,\r
+    bmdDeckControlModeError                            = /* 'moer' */ 0x6D6F6572,\r
+    bmdDeckControlMissedInPointError                   = /* 'mier' */ 0x6D696572,\r
+    bmdDeckControlDeckTimeoutError                     = /* 'dter' */ 0x64746572,\r
+    bmdDeckControlCommandFailedError                   = /* 'cfer' */ 0x63666572,\r
+    bmdDeckControlDeviceAlreadyOpenedError             = /* 'dalo' */ 0x64616C6F,\r
+    bmdDeckControlFailedToOpenDeviceError              = /* 'fder' */ 0x66646572,\r
+    bmdDeckControlInLocalModeError                     = /* 'lmer' */ 0x6C6D6572,\r
+    bmdDeckControlEndOfTapeError                       = /* 'eter' */ 0x65746572,\r
+    bmdDeckControlUserAbortError                       = /* 'uaer' */ 0x75616572,\r
+    bmdDeckControlNoTapeInDeckError                    = /* 'nter' */ 0x6E746572,\r
+    bmdDeckControlNoVideoFromCardError                 = /* 'nvfc' */ 0x6E766663,\r
+    bmdDeckControlNoCommunicationError                 = /* 'ncom' */ 0x6E636F6D,\r
+    bmdDeckControlBufferTooSmallError                  = /* 'btsm' */ 0x6274736D,\r
+    bmdDeckControlBadChecksumError                     = /* 'chks' */ 0x63686B73,\r
+    bmdDeckControlUnknownError                         = /* 'uner' */ 0x756E6572\r
+} BMDDeckControlError;\r
+\r
+\r
+/* Enum BMD3DPreviewFormat - Linked Frame preview format */\r
+\r
+typedef [v1_enum] enum _BMD3DPreviewFormat {\r
+    bmd3DPreviewFormatDefault                          = /* 'defa' */ 0x64656661,\r
+    bmd3DPreviewFormatLeftOnly                         = /* 'left' */ 0x6C656674,\r
+    bmd3DPreviewFormatRightOnly                        = /* 'righ' */ 0x72696768,\r
+    bmd3DPreviewFormatSideBySide                       = /* 'side' */ 0x73696465,\r
+    bmd3DPreviewFormatTopBottom                        = /* 'topb' */ 0x746F7062\r
+} BMD3DPreviewFormat;\r
+\r
+\r
+// Forward Declarations\r
+\r
+interface IDeckLinkVideoOutputCallback;\r
+interface IDeckLinkInputCallback;\r
+interface IDeckLinkMemoryAllocator;\r
+interface IDeckLinkAudioOutputCallback;\r
+interface IDeckLinkIterator;\r
+interface IDeckLinkAPIInformation;\r
+interface IDeckLinkDisplayModeIterator;\r
+interface IDeckLinkDisplayMode;\r
+interface IDeckLink;\r
+interface IDeckLinkOutput;\r
+interface IDeckLinkInput;\r
+interface IDeckLinkTimecode;\r
+interface IDeckLinkVideoFrame;\r
+interface IDeckLinkMutableVideoFrame;\r
+interface IDeckLinkVideoFrame3DExtensions;\r
+interface IDeckLinkVideoInputFrame;\r
+interface IDeckLinkVideoFrameAncillary;\r
+interface IDeckLinkAudioInputPacket;\r
+interface IDeckLinkScreenPreviewCallback;\r
+interface IDeckLinkGLScreenPreviewHelper;\r
+interface IDeckLinkConfiguration;\r
+interface IDeckLinkAttributes;\r
+interface IDeckLinkKeyer;\r
+interface IDeckLinkVideoConversion;\r
+interface IDeckLinkDeckControlStatusCallback;\r
+interface IDeckLinkDeckControl;\r
+\r
+\r
+/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */\r
+\r
+[\r
+    object,\r
+    uuid(20AA5225-1958-47CB-820B-80A8D521A6EE),\r
+    helpstring("Frame completion callback.")\r
+] interface IDeckLinkVideoOutputCallback : IUnknown\r
+{\r
+    HRESULT ScheduledFrameCompleted([in] IDeckLinkVideoFrame *completedFrame, [in] BMDOutputFrameCompletionResult result);\r
+    HRESULT ScheduledPlaybackHasStopped(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkInputCallback - Frame arrival callback. */\r
+\r
+[\r
+    object,\r
+    uuid(DD04E5EC-7415-42AB-AE4A-E80C4DFC044A),\r
+    helpstring("Frame arrival callback.")\r
+] interface IDeckLinkInputCallback : IUnknown\r
+{\r
+    HRESULT VideoInputFormatChanged([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode *newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r
+    HRESULT VideoInputFrameArrived([in] IDeckLinkVideoInputFrame* videoFrame, [in] IDeckLinkAudioInputPacket* audioPacket);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */\r
+\r
+[\r
+    object,\r
+    uuid(B36EB6E7-9D29-4AA8-92EF-843B87A289E8),\r
+    local, \r
+    helpstring("Memory allocator for video frames.")\r
+] interface IDeckLinkMemoryAllocator : IUnknown\r
+{\r
+    HRESULT AllocateBuffer([in] unsigned long bufferSize, [out] void **allocatedBuffer);\r
+    HRESULT ReleaseBuffer([in] void *buffer);\r
+\r
+    HRESULT Commit(void);\r
+    HRESULT Decommit(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */\r
+\r
+[\r
+    object,\r
+    uuid(403C681B-7F46-4A12-B993-2BB127084EE6),\r
+    local, \r
+    helpstring("Optional callback to allow audio samples to be pulled as required.")\r
+] interface IDeckLinkAudioOutputCallback : IUnknown\r
+{\r
+    HRESULT RenderAudioSamples([in] BOOL preroll);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkIterator - enumerates installed DeckLink hardware */\r
+\r
+[\r
+    object,\r
+    uuid(74E936FC-CC28-4A67-81A0-1E94E52D4E69),\r
+    helpstring("enumerates installed DeckLink hardware")\r
+] interface IDeckLinkIterator : IUnknown\r
+{\r
+    HRESULT Next([out] IDeckLink **deckLinkInstance);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */\r
+\r
+[\r
+    object,\r
+    uuid(7BEA3C68-730D-4322-AF34-8A7152B532A4),\r
+    helpstring("DeckLinkAPI attribute interface")\r
+] interface IDeckLinkAPIInformation : IUnknown\r
+{\r
+    HRESULT GetFlag([in] BMDDeckLinkAPIInformationID cfgID, [out] BOOL *value);\r
+    HRESULT GetInt([in] BMDDeckLinkAPIInformationID cfgID, [out] LONGLONG *value);\r
+    HRESULT GetFloat([in] BMDDeckLinkAPIInformationID cfgID, [out] double *value);\r
+    HRESULT GetString([in] BMDDeckLinkAPIInformationID cfgID, [out] BSTR *value);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */\r
+\r
+[\r
+    object,\r
+    uuid(9C88499F-F601-4021-B80B-032E4EB41C35),\r
+    helpstring("enumerates over supported input/output display modes.")\r
+] interface IDeckLinkDisplayModeIterator : IUnknown\r
+{\r
+    HRESULT Next([out] IDeckLinkDisplayMode **deckLinkDisplayMode);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkDisplayMode - represents a display mode */\r
+\r
+[\r
+    object,\r
+    uuid(3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78),\r
+    helpstring("represents a display mode")\r
+] interface IDeckLinkDisplayMode : IUnknown\r
+{\r
+    HRESULT GetName([out] BSTR *name);\r
+    BMDDisplayMode GetDisplayMode(void);\r
+    long GetWidth(void);\r
+    long GetHeight(void);\r
+    HRESULT GetFrameRate([out] BMDTimeValue *frameDuration, [out] BMDTimeScale *timeScale);\r
+    BMDFieldDominance GetFieldDominance(void);\r
+    BMDDisplayModeFlags GetFlags(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLink - represents a DeckLink device */\r
+\r
+[\r
+    object,\r
+    uuid(62BFF75D-6569-4E55-8D4D-66AA03829ABC),\r
+    helpstring("represents a DeckLink device")\r
+] interface IDeckLink : IUnknown\r
+{\r
+    HRESULT GetModelName([out] BSTR *modelName);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */\r
+\r
+[\r
+    object,\r
+    uuid(A3EF0963-0862-44ED-92A9-EE89ABF431C7),\r
+    local, \r
+    helpstring("Created by QueryInterface from IDeckLink.")\r
+] interface IDeckLinkOutput : IUnknown\r
+{\r
+    HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoOutputFlags flags, [out] BMDDisplayModeSupport *result, [out] IDeckLinkDisplayMode **resultDisplayMode);\r
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator);\r
+\r
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback);\r
+\r
+    /* Video Output */\r
+\r
+    HRESULT EnableVideoOutput([in] BMDDisplayMode displayMode, [in] BMDVideoOutputFlags flags);\r
+    HRESULT DisableVideoOutput(void);\r
+\r
+    HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator);\r
+    HRESULT CreateVideoFrame([in] long width, [in] long height, [in] long rowBytes, [in] BMDPixelFormat pixelFormat, [in] BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame **outFrame);\r
+    HRESULT CreateAncillaryData([in] BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer);\r
+\r
+    HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame *theFrame);\r
+    HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame *theFrame, [in] BMDTimeValue displayTime, [in] BMDTimeValue displayDuration, [in] BMDTimeScale timeScale);\r
+    HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback *theCallback);\r
+    HRESULT GetBufferedVideoFrameCount([out] unsigned long *bufferedFrameCount);\r
+\r
+    /* Audio Output */\r
+\r
+    HRESULT EnableAudioOutput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned long channelCount, [in] BMDAudioOutputStreamType streamType);\r
+    HRESULT DisableAudioOutput(void);\r
+\r
+    HRESULT WriteAudioSamplesSync([in] void *buffer, [in] unsigned long sampleFrameCount, [out] unsigned long *sampleFramesWritten);\r
+\r
+    HRESULT BeginAudioPreroll(void);\r
+    HRESULT EndAudioPreroll(void);\r
+    HRESULT ScheduleAudioSamples([in] void *buffer, [in] unsigned long sampleFrameCount, [in] BMDTimeValue streamTime, [in] BMDTimeScale timeScale, [out] unsigned long *sampleFramesWritten);\r
+\r
+    HRESULT GetBufferedAudioSampleFrameCount([out] unsigned long *bufferedSampleFrameCount);\r
+    HRESULT FlushBufferedAudioSamples(void);\r
+\r
+    HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback);\r
+\r
+    /* Output Control */\r
+\r
+    HRESULT StartScheduledPlayback([in] BMDTimeValue playbackStartTime, [in] BMDTimeScale timeScale, [in] double playbackSpeed);\r
+    HRESULT StopScheduledPlayback([in] BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, [in] BMDTimeScale timeScale);\r
+    HRESULT IsScheduledPlaybackRunning([out] BOOL *active);\r
+    HRESULT GetScheduledStreamTime([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *streamTime, [out] double *playbackSpeed);\r
+    HRESULT GetReferenceStatus([out] BMDReferenceStatus *referenceStatus);\r
+\r
+    /* Hardware Timing */\r
+\r
+    HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */\r
+\r
+[\r
+    object,\r
+    uuid(6D40EF78-28B9-4E21-990D-95BB7750A04F),\r
+    helpstring("Created by QueryInterface from IDeckLink.")\r
+] interface IDeckLinkInput : IUnknown\r
+{\r
+    HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags, [out] BMDDisplayModeSupport *result, [out] IDeckLinkDisplayMode **resultDisplayMode);\r
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator);\r
+\r
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback);\r
+\r
+    /* Video Input */\r
+\r
+    HRESULT EnableVideoInput([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags);\r
+    HRESULT DisableVideoInput(void);\r
+    HRESULT GetAvailableVideoFrameCount([out] unsigned long *availableFrameCount);\r
+\r
+    /* Audio Input */\r
+\r
+    HRESULT EnableAudioInput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned long channelCount);\r
+    HRESULT DisableAudioInput(void);\r
+    HRESULT GetAvailableAudioSampleFrameCount([out] unsigned long *availableSampleFrameCount);\r
+\r
+    /* Input Control */\r
+\r
+    HRESULT StartStreams(void);\r
+    HRESULT StopStreams(void);\r
+    HRESULT PauseStreams(void);\r
+    HRESULT FlushStreams(void);\r
+    HRESULT SetCallback([in] IDeckLinkInputCallback *theCallback);\r
+\r
+    /* Hardware Timing */\r
+\r
+    HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */\r
+\r
+[\r
+    object,\r
+    uuid(BC6CFBD3-8317-4325-AC1C-1216391E9340),\r
+    helpstring("Used for video frame timecode representation.")\r
+] interface IDeckLinkTimecode : IUnknown\r
+{\r
+    BMDTimecodeBCD GetBCD(void);\r
+    HRESULT GetComponents([out] unsigned char *hours, [out] unsigned char *minutes, [out] unsigned char *seconds, [out] unsigned char *frames);\r
+    HRESULT GetString([out] BSTR *timecode);\r
+    BMDTimecodeFlags GetFlags(void);\r
+    HRESULT GetTimecodeUserBits([out] BMDTimecodeUserBits *userBits);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */\r
+\r
+[\r
+    object,\r
+    uuid(3F716FE0-F023-4111-BE5D-EF4414C05B17),\r
+    local, \r
+    helpstring("Interface to encapsulate a video frame; can be caller-implemented.")\r
+] interface IDeckLinkVideoFrame : IUnknown\r
+{\r
+    long GetWidth(void);\r
+    long GetHeight(void);\r
+    long GetRowBytes(void);\r
+    BMDPixelFormat GetPixelFormat(void);\r
+    BMDFrameFlags GetFlags(void);\r
+    HRESULT GetBytes([out] void **buffer);\r
+\r
+    HRESULT GetTimecode([in] BMDTimecodeFormat format, [out] IDeckLinkTimecode **timecode);\r
+    HRESULT GetAncillaryData([out] IDeckLinkVideoFrameAncillary **ancillary);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */\r
+\r
+[\r
+    object,\r
+    uuid(69E2639F-40DA-4E19-B6F2-20ACE815C390),\r
+    local, \r
+    helpstring("Created by IDeckLinkOutput::CreateVideoFrame.")\r
+] interface IDeckLinkMutableVideoFrame : IDeckLinkVideoFrame\r
+{\r
+    HRESULT SetFlags([in] BMDFrameFlags newFlags);\r
+\r
+    HRESULT SetTimecode([in] BMDTimecodeFormat format, [in] IDeckLinkTimecode *timecode);\r
+    HRESULT SetTimecodeFromComponents([in] BMDTimecodeFormat format, [in] unsigned char hours, [in] unsigned char minutes, [in] unsigned char seconds, [in] unsigned char frames, [in] BMDTimecodeFlags flags);\r
+    HRESULT SetAncillaryData([in] IDeckLinkVideoFrameAncillary *ancillary);\r
+    HRESULT SetTimecodeUserBits([in] BMDTimecodeFormat format, [in] BMDTimecodeUserBits userBits);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */\r
+\r
+[\r
+    object,\r
+    uuid(DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7),\r
+    local, \r
+    helpstring("Optional interface implemented on IDeckLinkVideoFrame to support 3D frames")\r
+] interface IDeckLinkVideoFrame3DExtensions : IUnknown\r
+{\r
+    BMDVideo3DPackingFormat Get3DPackingFormat(void);\r
+    HRESULT GetFrameForRightEye([out] IDeckLinkVideoFrame* *rightEyeFrame);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */\r
+\r
+[\r
+    object,\r
+    uuid(05CFE374-537C-4094-9A57-680525118F44),\r
+    local, \r
+    helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.")\r
+] interface IDeckLinkVideoInputFrame : IDeckLinkVideoFrame\r
+{\r
+    HRESULT GetStreamTime([out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration, [in] BMDTimeScale timeScale);\r
+    HRESULT GetHardwareReferenceTimestamp([in] BMDTimeScale timeScale, [out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkVideoFrameAncillary - Obtained through QueryInterface() on an IDeckLinkVideoFrame object. */\r
+\r
+[\r
+    object,\r
+    uuid(732E723C-D1A4-4E29-9E8E-4A88797A0004),\r
+    local, \r
+    helpstring("Obtained through QueryInterface() on an IDeckLinkVideoFrame object.")\r
+] interface IDeckLinkVideoFrameAncillary : IUnknown\r
+{\r
+\r
+    HRESULT GetBufferForVerticalBlankingLine([in] unsigned long lineNumber, [out] void **buffer);\r
+    BMDPixelFormat GetPixelFormat(void);\r
+    BMDDisplayMode GetDisplayMode(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */\r
+\r
+[\r
+    object,\r
+    uuid(E43D5870-2894-11DE-8C30-0800200C9A66),\r
+    local, \r
+    helpstring("Provided by the IDeckLinkInput callback.")\r
+] interface IDeckLinkAudioInputPacket : IUnknown\r
+{\r
+    long GetSampleFrameCount(void);\r
+    HRESULT GetBytes([out] void **buffer);\r
+    HRESULT GetPacketTime([out] BMDTimeValue *packetTime, [in] BMDTimeScale timeScale);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */\r
+\r
+[\r
+    object,\r
+    uuid(B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438),\r
+    local, \r
+    helpstring("Screen preview callback")\r
+] interface IDeckLinkScreenPreviewCallback : IUnknown\r
+{\r
+    HRESULT DrawFrame([in] IDeckLinkVideoFrame *theFrame);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */\r
+\r
+[\r
+    object,\r
+    uuid(504E2209-CAC7-4C1A-9FB4-C5BB6274D22F),\r
+    local, \r
+    helpstring("Created with CoCreateInstance().")\r
+] interface IDeckLinkGLScreenPreviewHelper : IUnknown\r
+{\r
+\r
+    /* Methods must be called with OpenGL context set */\r
+\r
+    HRESULT InitializeGL(void);\r
+    HRESULT PaintGL(void);\r
+    HRESULT SetFrame([in] IDeckLinkVideoFrame *theFrame);\r
+    HRESULT Set3DPreviewFormat([in] BMD3DPreviewFormat previewFormat);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */\r
+\r
+[\r
+    object,\r
+    uuid(C679A35B-610C-4D09-B748-1D0478100FC0),\r
+    local, \r
+    helpstring("DeckLink Configuration interface")\r
+] interface IDeckLinkConfiguration : IUnknown\r
+{\r
+    HRESULT SetFlag([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value);\r
+    HRESULT GetFlag([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL *value);\r
+    HRESULT SetInt([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value);\r
+    HRESULT GetInt([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG *value);\r
+    HRESULT SetFloat([in] BMDDeckLinkConfigurationID cfgID, [in] double value);\r
+    HRESULT GetFloat([in] BMDDeckLinkConfigurationID cfgID, [out] double *value);\r
+    HRESULT SetString([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value);\r
+    HRESULT GetString([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR *value);\r
+    HRESULT WriteConfigurationToPreferences(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkAttributes - DeckLink Attribute interface */\r
+\r
+[\r
+    object,\r
+    uuid(ABC11843-D966-44CB-96E2-A1CB5D3135C4),\r
+    local, \r
+    helpstring("DeckLink Attribute interface")\r
+] interface IDeckLinkAttributes : IUnknown\r
+{\r
+    HRESULT GetFlag([in] BMDDeckLinkAttributeID cfgID, [out] BOOL *value);\r
+    HRESULT GetInt([in] BMDDeckLinkAttributeID cfgID, [out] LONGLONG *value);\r
+    HRESULT GetFloat([in] BMDDeckLinkAttributeID cfgID, [out] double *value);\r
+    HRESULT GetString([in] BMDDeckLinkAttributeID cfgID, [out] BSTR *value);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkKeyer - DeckLink Keyer interface */\r
+\r
+[\r
+    object,\r
+    uuid(89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3),\r
+    local, \r
+    helpstring("DeckLink Keyer interface")\r
+] interface IDeckLinkKeyer : IUnknown\r
+{\r
+    HRESULT Enable([in] BOOL isExternal);\r
+    HRESULT SetLevel([in] unsigned char level);\r
+    HRESULT RampUp([in] unsigned long numberOfFrames);\r
+    HRESULT RampDown([in] unsigned long numberOfFrames);\r
+    HRESULT Disable(void);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */\r
+\r
+[\r
+    object,\r
+    uuid(3BBCB8A2-DA2C-42D9-B5D8-88083644E99A),\r
+    local, \r
+    helpstring("Created with CoCreateInstance().")\r
+] interface IDeckLinkVideoConversion : IUnknown\r
+{\r
+    HRESULT ConvertFrame([in] IDeckLinkVideoFrame* srcFrame, [in] IDeckLinkVideoFrame* dstFrame);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */\r
+\r
+[\r
+    object,\r
+    uuid(E5F693C1-4283-4716-B18F-C1431521955B),\r
+    helpstring("Deck control state change callback.")\r
+] interface IDeckLinkDeckControlStatusCallback : IUnknown\r
+{\r
+    HRESULT TimecodeUpdate([in] BMDTimecodeBCD currentTimecode);\r
+    HRESULT VTRControlStateChanged([in] BMDDeckControlVTRControlState newState, [in] BMDDeckControlError error);\r
+    HRESULT DeckControlEventReceived([in] BMDDeckControlEvent event, [in] BMDDeckControlError error);\r
+    HRESULT DeckControlStatusChanged([in] BMDDeckControlStatusFlags flags, [in] unsigned long mask);\r
+};\r
+\r
+\r
+/* Interface IDeckLinkDeckControl - Deck Control main interface */\r
+\r
+[\r
+    object,\r
+    uuid(522A9E39-0F3C-4742-94EE-D80DE335DA1D),\r
+    helpstring("Deck Control main interface")\r
+] interface IDeckLinkDeckControl : IUnknown\r
+{\r
+    HRESULT Open([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError *error);\r
+    HRESULT Close([in] BOOL standbyOn);\r
+    HRESULT GetCurrentState([out] BMDDeckControlMode *mode, [out] BMDDeckControlVTRControlState *vtrControlState, [out] BMDDeckControlStatusFlags *flags);\r
+    HRESULT SetStandby([in] BOOL standbyOn);\r
+    HRESULT SendCommand([in] unsigned char *inBuffer, [in] unsigned long inBufferSize, [out] unsigned char *outBuffer, [out] unsigned long *outDataSize, [in] unsigned long outBufferSize, [out] BMDDeckControlError *error);\r
+    HRESULT Play([out] BMDDeckControlError *error);\r
+    HRESULT Stop([out] BMDDeckControlError *error);\r
+    HRESULT TogglePlayStop([out] BMDDeckControlError *error);\r
+    HRESULT Eject([out] BMDDeckControlError *error);\r
+    HRESULT GoToTimecode([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError *error);\r
+    HRESULT FastForward([in] BOOL viewTape, [out] BMDDeckControlError *error);\r
+    HRESULT Rewind([in] BOOL viewTape, [out] BMDDeckControlError *error);\r
+    HRESULT StepForward([out] BMDDeckControlError *error);\r
+    HRESULT StepBack([out] BMDDeckControlError *error);\r
+    HRESULT Jog([in] double rate, [out] BMDDeckControlError *error);\r
+    HRESULT Shuttle([in] double rate, [out] BMDDeckControlError *error);\r
+    HRESULT GetTimecodeString([out] BSTR *currentTimeCode, [out] BMDDeckControlError *error);\r
+    HRESULT GetTimecode([out] IDeckLinkTimecode **currentTimecode, [out] BMDDeckControlError *error);\r
+    HRESULT GetTimecodeBCD([out] BMDTimecodeBCD *currentTimecode, [out] BMDDeckControlError *error);\r
+    HRESULT SetPreroll([in] unsigned long prerollSeconds);\r
+    HRESULT GetPreroll([out] unsigned long *prerollSeconds);\r
+    HRESULT SetExportOffset([in] long exportOffsetFields);\r
+    HRESULT GetExportOffset([out] long *exportOffsetFields);\r
+    HRESULT GetManualExportOffset([out] long *deckManualExportOffsetFields);\r
+    HRESULT SetCaptureOffset([in] long captureOffsetFields);\r
+    HRESULT GetCaptureOffset([out] long *captureOffsetFields);\r
+    HRESULT StartExport([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError *error);\r
+    HRESULT StartCapture([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError *error);\r
+    HRESULT GetDeviceID([out] unsigned short *deviceId, [out] BMDDeckControlError *error);\r
+    HRESULT Abort(void);\r
+    HRESULT CrashRecordStart([out] BMDDeckControlError *error);\r
+    HRESULT CrashRecordStop([out] BMDDeckControlError *error);\r
+    HRESULT SetCallback([in] IDeckLinkDeckControlStatusCallback *callback);\r
+};\r
+\r
+\r
+/* Coclasses */\r
+\r
+importlib("stdole2.tlb");\r
+\r
+[\r
+    uuid(D9EDA3B3-2887-41FA-B724-017CF1EB1D37),\r
+    helpstring("CDeckLinkIterator Class")\r
+] coclass CDeckLinkIterator\r
+{\r
+    [default] interface IDeckLinkIterator;\r
+};\r
+\r
+[\r
+    uuid(263CA19F-ED09-482E-9F9D-84005783A237),\r
+    helpstring("CDeckLinkAPIInformation Class")\r
+] coclass CDeckLinkAPIInformation\r
+{\r
+    [default] interface IDeckLinkAPIInformation;\r
+};\r
+\r
+[\r
+    uuid(F63E77C7-B655-4A4A-9AD0-3CA85D394343),\r
+    helpstring("CDeckLinkGLScreenPreviewHelper Class")\r
+] coclass CDeckLinkGLScreenPreviewHelper\r
+{\r
+    [default] interface IDeckLinkGLScreenPreviewHelper;\r
+};\r
+\r
+[\r
+    uuid(7DBBBB11-5B7B-467D-AEA4-CEA468FD368C),\r
+    helpstring("CDeckLinkVideoConversion Class")\r
+] coclass CDeckLinkVideoConversion\r
+{\r
+    [default] interface IDeckLinkVideoConversion;\r
+};\r
+\r
+\r
+// import deprecated interfaces\r
+#include "DeckLinkAPI_v7_9.idl"\r
+#include "DeckLinkAPI_v7_6.idl"\r
+#include "DeckLinkAPI_v7_3.idl"\r
+#include "DeckLinkAPI_v7_1.idl"\r
+};\r
diff --git a/modules/decklink/interop/DeckLinkAPIVersion.h b/modules/decklink/interop/DeckLinkAPIVersion.h
new file mode 100644 (file)
index 0000000..e799570
--- /dev/null
@@ -0,0 +1,37 @@
+/* -LICENSE-START-
+ * ** Copyright (c) 2011 Blackmagic Design
+ * **
+ * ** Permission is hereby granted, free of charge, to any person or organization
+ * ** obtaining a copy of the software and accompanying documentation covered by
+ * ** this license (the "Software") to use, reproduce, display, distribute,
+ * ** execute, and transmit the Software, and to prepare derivative works of the
+ * ** Software, and to permit third-parties to whom the Software is furnished to
+ * ** do so, all subject to the following:
+ * ** 
+ * ** The copyright notices in the Software and this entire statement, including
+ * ** the above license grant, this restriction and the following disclaimer,
+ * ** must be included in all copies of the Software, in whole or in part, and
+ * ** all derivative works of the Software, unless such copies or derivative
+ * ** works are solely in the form of machine-executable object code generated by
+ * ** a source language processor.
+ * ** 
+ * ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * ** DEALINGS IN THE SOFTWARE.
+ * ** -LICENSE-END-
+ * */
+
+/* DeckLinkAPIVersion.h */
+
+#ifndef __DeckLink_API_Verison_h__
+#define __DeckLink_API_Version_h__
+
+#define BLACKMAGIC_DECKLINK_API_VERSION                                        0x08000000
+#define BLACKMAGIC_DECKLINK_API_VERSION_STRING                 "8.0"
+
+#endif // __DeckLink_API_Version_h__
+
diff --git a/modules/decklink/interop/DeckLinkAPI_v7_1.idl b/modules/decklink/interop/DeckLinkAPI_v7_1.idl
new file mode 100644 (file)
index 0000000..20d4e5f
--- /dev/null
@@ -0,0 +1,160 @@
+/* -LICENSE-START-\r
+** Copyright (c) 2009 Blackmagic Design\r
+**\r
+** Permission is hereby granted, free of charge, to any person or organization\r
+** obtaining a copy of the software and accompanying documentation covered by\r
+** this license (the "Software") to use, reproduce, display, distribute,\r
+** execute, and transmit the Software, and to prepare derivative works of the\r
+** Software, and to permit third-parties to whom the Software is furnished to\r
+** do so, all subject to the following:\r
+** \r
+** The copyright notices in the Software and this entire statement, including\r
+** the above license grant, this restriction and the following disclaimer,\r
+** must be included in all copies of the Software, in whole or in part, and\r
+** all derivative works of the Software, unless such copies or derivative\r
+** works are solely in the form of machine-executable object code generated by\r
+** a source language processor.\r
+** \r
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\r
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\r
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\r
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+** DEALINGS IN THE SOFTWARE.\r
+** -LICENSE-END-\r
+*/\r
+/* DeckLinkAPI_v7_1.idl */\r
+\r
+       interface IDeckLinkDisplayModeIterator_v7_1;\r
+       interface IDeckLinkDisplayMode_v7_1;\r
+       interface IDeckLinkVideoFrame_v7_1;\r
+       interface IDeckLinkVideoInputFrame_v7_1;\r
+       interface IDeckLinkAudioInputPacket_v7_1;\r
+       \r
+       [object, uuid(B28131B6-59AC-4857-B5AC-CD75D5883E2F),\r
+        helpstring("IDeckLinkDisplayModeIterator_v7_1 enumerates over supported input/output display modes.")]\r
+       interface IDeckLinkDisplayModeIterator_v7_1 : IUnknown\r
+       {\r
+               HRESULT         Next ([out] IDeckLinkDisplayMode_v7_1** deckLinkDisplayMode);\r
+       };\r
+\r
+\r
+       [object, uuid(AF0CD6D5-8376-435E-8433-54F9DD530AC3),\r
+        helpstring("IDeckLinkDisplayMode_v7_1 represents a display mode")]\r
+       interface IDeckLinkDisplayMode_v7_1 : IUnknown\r
+       {\r
+               HRESULT                         GetName ([out] BSTR* name);\r
+               BMDDisplayMode          GetDisplayMode ();\r
+               long                            GetWidth ();\r
+               long                            GetHeight ();\r
+               HRESULT                         GetFrameRate ([out] BMDTimeValue *frameDuration, [out] BMDTimeScale *timeScale);\r
+       };\r
+       \r
+       [object, uuid(EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9),\r
+     helpstring("IDeckLinkVideoOutputCallback. Frame completion callback.")]\r
+    interface IDeckLinkVideoOutputCallback_v7_1 : IUnknown\r
+    {\r
+        HRESULT                ScheduledFrameCompleted ([in] IDeckLinkVideoFrame_v7_1* completedFrame, [in] BMDOutputFrameCompletionResult result);\r
+    };\r
+       \r
+    [object, uuid(7F94F328-5ED4-4E9F-9729-76A86BDC99CC),\r
+     helpstring("IDeckLinkInputCallback_v7_1. Frame arrival callback.")]\r
+    interface IDeckLinkInputCallback_v7_1 : IUnknown\r
+    {\r
+        HRESULT                VideoInputFrameArrived ([in] IDeckLinkVideoInputFrame_v7_1* videoFrame, [in] IDeckLinkAudioInputPacket_v7_1* audioPacket);\r
+    };\r
+       \r
+\r
+    [object, uuid(AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5), local,\r
+     helpstring("IDeckLinkOutput_v7_1.  Created by QueryInterface from IDeckLink.")]\r
+    interface IDeckLinkOutput_v7_1 : IUnknown\r
+    {\r
+               HRESULT         DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);\r
+               HRESULT         GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator_v7_1 **iterator);\r
+               \r
+               // Video output\r
+        HRESULT                EnableVideoOutput (BMDDisplayMode displayMode);\r
+        HRESULT                DisableVideoOutput ();\r
+               \r
+               HRESULT         SetVideoOutputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator);\r
+        HRESULT                CreateVideoFrame (long width, long height, long rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1** outFrame);\r
+        HRESULT                CreateVideoFrameFromBuffer (void* buffer, long width, long height, long rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1** outFrame);\r
+\r
+        HRESULT                DisplayVideoFrameSync (IDeckLinkVideoFrame_v7_1* theFrame);\r
+        HRESULT                ScheduleVideoFrame (IDeckLinkVideoFrame_v7_1* theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale);\r
+        HRESULT                SetScheduledFrameCompletionCallback ([in] IDeckLinkVideoOutputCallback_v7_1* theCallback);\r
+               \r
+               // Audio output\r
+               HRESULT         EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount);\r
+               HRESULT         DisableAudioOutput ();\r
+               \r
+               HRESULT         WriteAudioSamplesSync (void* buffer, unsigned long sampleFrameCount, [out] unsigned long *sampleFramesWritten);\r
+               \r
+               HRESULT         BeginAudioPreroll ();\r
+               HRESULT         EndAudioPreroll ();\r
+               HRESULT         ScheduleAudioSamples (void* buffer, unsigned long sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned long *sampleFramesWritten);\r
+               \r
+               HRESULT         GetBufferedAudioSampleFrameCount ( [out] unsigned long *bufferedSampleCount);\r
+               HRESULT         FlushBufferedAudioSamples ();\r
+               \r
+               HRESULT         SetAudioCallback ( [in] IDeckLinkAudioOutputCallback* theCallback);\r
+               \r
+               // Output control\r
+        HRESULT                StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed);\r
+        HRESULT                StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, BMDTimeValue *actualStopTime, BMDTimeScale timeScale);\r
+        HRESULT                GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, BMDTimeValue *elapsedTimeSinceSchedulerBegan);\r
+    };\r
+\r
+    [object, uuid(2B54EDEF-5B32-429F-BA11-BB990596EACD),\r
+     helpstring("IDeckLinkInput_v7_1.  Created by QueryInterface from IDeckLink.")]\r
+    interface IDeckLinkInput_v7_1 : IUnknown\r
+    {\r
+               HRESULT         DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);\r
+               HRESULT         GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator_v7_1 **iterator);\r
+               \r
+               // Video input\r
+               HRESULT         EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags);\r
+               HRESULT         DisableVideoInput ();\r
+               \r
+               // Audio input\r
+               HRESULT         EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount);\r
+               HRESULT         DisableAudioInput ();\r
+               HRESULT         ReadAudioSamples (void* buffer, unsigned long sampleFrameCount, [out] unsigned long *sampleFramesRead, [out] BMDTimeValue *audioPacketTime, BMDTimeScale timeScale);\r
+               HRESULT         GetBufferedAudioSampleFrameCount ( [out] unsigned long *bufferedSampleCount);\r
+               \r
+               // Input control\r
+               HRESULT         StartStreams ();\r
+               HRESULT         StopStreams ();\r
+               HRESULT         PauseStreams ();\r
+               HRESULT         SetCallback ([in] IDeckLinkInputCallback_v7_1* theCallback);\r
+    };\r
+       \r
+       [object, uuid(333F3A10-8C2D-43CF-B79D-46560FEEA1CE), local,\r
+     helpstring("IDeckLinkVideoFrame_v7_1.  Created by IDeckLinkVideoOutput::CreateVideoFrame.")]\r
+    interface IDeckLinkVideoFrame_v7_1 : IUnknown\r
+    {\r
+        long                           GetWidth ();\r
+        long                           GetHeight ();\r
+        long                           GetRowBytes ();\r
+        BMDPixelFormat         GetPixelFormat ();\r
+        BMDFrameFlags          GetFlags ();\r
+        HRESULT                                GetBytes (void* *buffer);\r
+    };\r
+       \r
+       [object, uuid(C8B41D95-8848-40EE-9B37-6E3417FB114B), local,\r
+     helpstring("IDeckLinkVideoInputFrame_v7_1.  Provided by the IDeckLinkVideoInput frame arrival callback.")]\r
+    interface IDeckLinkVideoInputFrame_v7_1 : IDeckLinkVideoFrame_v7_1\r
+    {\r
+        HRESULT                                GetFrameTime (BMDTimeValue *frameTime, BMDTimeValue *frameDuration, BMDTimeScale timeScale);\r
+    };\r
+       \r
+       [object, uuid(C86DE4F6-A29F-42E3-AB3A-1363E29F0788), local,\r
+     helpstring("IDeckLinkAudioInputPacket_v7_1.  Provided by the IDeckLinkInput callback.")]\r
+    interface IDeckLinkAudioInputPacket_v7_1 : IUnknown\r
+    {\r
+               long                            GetSampleCount ();\r
+               HRESULT                         GetBytes (void* *buffer);\r
+               HRESULT                         GetAudioPacketTime (BMDTimeValue *packetTime, BMDTimeScale timeScale);\r
+    };\r
+       \r
diff --git a/modules/decklink/interop/DeckLinkAPI_v7_3.idl b/modules/decklink/interop/DeckLinkAPI_v7_3.idl
new file mode 100644 (file)
index 0000000..da367d6
--- /dev/null
@@ -0,0 +1,157 @@
+/* -LICENSE-START-
+** Copyright (c) 2009 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+** 
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+** 
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+/* Forward Declarations */
+
+interface IDeckLinkInputCallback_v7_3;
+interface IDeckLinkOutput_v7_3;
+interface IDeckLinkInput_v7_3;
+interface IDeckLinkVideoInputFrame_v7_3;
+
+/* End Forward Declarations */
+
+
+/* Interface IDeckLinkInputCallback - Frame arrival callback. */
+
+[
+    object,
+    uuid(FD6F311D-4D00-444B-9ED4-1F25B5730AD0),
+    helpstring("Frame arrival callback.")
+] interface IDeckLinkInputCallback_v7_3 : IUnknown
+{
+    HRESULT VideoInputFormatChanged([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode_v7_6 *newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags);
+    HRESULT VideoInputFrameArrived([in] IDeckLinkVideoInputFrame_v7_3 *videoFrame, [in] IDeckLinkAudioInputPacket *audioPacket);
+};
+
+/* End Interface IDeckLinkInputCallback */
+
+
+/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */
+
+[
+    object,
+    uuid(271C65E3-C323-4344-A30F-D908BCB20AA3),
+    local, 
+    helpstring("Created by QueryInterface from IDeckLink.")
+] interface IDeckLinkOutput_v7_3 : IUnknown
+{
+    HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback);
+
+    /* Video Output */
+
+    HRESULT EnableVideoOutput(BMDDisplayMode displayMode, BMDVideoOutputFlags flags);
+    HRESULT DisableVideoOutput(void);
+
+    HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator);
+    HRESULT CreateVideoFrame(long width, long height, long rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame_v7_6 **outFrame);
+    HRESULT CreateAncillaryData(BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer);
+
+    HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame_v7_6 *theFrame);
+    HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale);
+    HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback *theCallback);
+    HRESULT GetBufferedVideoFrameCount([out] unsigned long *bufferedFrameCount);
+
+    /* Audio Output */
+
+    HRESULT EnableAudioOutput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount, BMDAudioOutputStreamType streamType);
+    HRESULT DisableAudioOutput(void);
+
+    HRESULT WriteAudioSamplesSync([in] void *buffer, unsigned long sampleFrameCount, [out] unsigned long *sampleFramesWritten);
+
+    HRESULT BeginAudioPreroll(void);
+    HRESULT EndAudioPreroll(void);
+    HRESULT ScheduleAudioSamples([in] void *buffer, unsigned long sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned long *sampleFramesWritten);
+
+    HRESULT GetBufferedAudioSampleFrameCount([out] unsigned long *bufferedSampleFrameCount);
+    HRESULT FlushBufferedAudioSamples(void);
+
+    HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback);
+
+    /* Output Control */
+
+    HRESULT StartScheduledPlayback(BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed);
+    HRESULT StopScheduledPlayback(BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, BMDTimeScale timeScale);
+    HRESULT IsScheduledPlaybackRunning([out] BOOL *active);
+    HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *elapsedTimeSinceSchedulerBegan);
+};
+
+/* End Interface IDeckLinkOutput */
+
+/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */
+
+[
+    object,
+    uuid(4973F012-9925-458C-871C-18774CDBBECB),
+    helpstring("Created by QueryInterface from IDeckLink.")
+] interface IDeckLinkInput_v7_3 : IUnknown
+{
+    HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback);
+
+    /* Video Input */
+
+    HRESULT EnableVideoInput(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags);
+    HRESULT DisableVideoInput(void);
+    HRESULT GetAvailableVideoFrameCount([out] unsigned long *availableFrameCount);
+
+    /* Audio Input */
+
+    HRESULT EnableAudioInput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount);
+    HRESULT DisableAudioInput(void);
+    HRESULT GetAvailableAudioSampleFrameCount([out] unsigned long *availableSampleFrameCount);
+
+    /* Input Control */
+
+    HRESULT StartStreams(void);
+    HRESULT StopStreams(void);
+    HRESULT PauseStreams(void);
+    HRESULT FlushStreams(void);
+    HRESULT SetCallback([in] IDeckLinkInputCallback_v7_3 *theCallback);
+};
+
+/* End Interface IDeckLinkInput */
+
+
+/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */
+
+[
+    object,
+    uuid(CF317790-2894-11DE-8C30-0800200C9A66),
+    local, 
+    helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.")
+] interface IDeckLinkVideoInputFrame_v7_3 : IDeckLinkVideoFrame_v7_6
+{
+    HRESULT GetStreamTime([out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration, BMDTimeScale timeScale);
+};
+
+/* End Interface IDeckLinkVideoInputFrame */
+
diff --git a/modules/decklink/interop/DeckLinkAPI_v7_6.idl b/modules/decklink/interop/DeckLinkAPI_v7_6.idl
new file mode 100644 (file)
index 0000000..271801c
--- /dev/null
@@ -0,0 +1,396 @@
+/* -LICENSE-START-
+** Copyright (c) 2009 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+** 
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+** 
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+/* Enum BMDVideoConnection - Video connection types */
+
+typedef [v1_enum] enum  _BMDVideoConnection_v7_6 {
+    bmdVideoConnectionSDI_v7_6                              = /* 'sdi ' */ 0x73646920,
+    bmdVideoConnectionHDMI_v7_6                             = /* 'hdmi' */ 0x68646D69,
+    bmdVideoConnectionOpticalSDI_v7_6                       = /* 'opti' */ 0x6F707469,
+    bmdVideoConnectionComponent_v7_6                        = /* 'cpnt' */ 0x63706E74,
+    bmdVideoConnectionComposite_v7_6                        = /* 'cmst' */ 0x636D7374,
+    bmdVideoConnectionSVideo_v7_6                           = /* 'svid' */ 0x73766964
+} BMDVideoConnection_v7_6;
+
+
+
+/* Forward Declarations */
+
+interface IDeckLinkDisplayModeIterator_v7_6;
+interface IDeckLinkDisplayMode_v7_6;
+interface IDeckLinkOutput_v7_6;
+interface IDeckLinkInput_v7_6;
+interface IDeckLinkTimecode_v7_6;
+interface IDeckLinkVideoFrame_v7_6;
+interface IDeckLinkMutableVideoFrame_v7_6;
+interface IDeckLinkVideoInputFrame_v7_6;
+interface IDeckLinkScreenPreviewCallback_v7_6;
+interface IDeckLinkGLScreenPreviewHelper_v7_6;
+interface IDeckLinkVideoConversion_v7_6;
+interface IDeckLinkConfiguration_v7_6;
+
+
+/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */
+
+[
+    object,
+    uuid(E763A626-4A3C-49D1-BF13-E7AD3692AE52),
+    helpstring("Frame completion callback.")
+] interface IDeckLinkVideoOutputCallback_v7_6 : IUnknown
+{
+    HRESULT ScheduledFrameCompleted([in] IDeckLinkVideoFrame_v7_6 *completedFrame, [in] BMDOutputFrameCompletionResult result);
+    HRESULT ScheduledPlaybackHasStopped(void);
+};
+
+
+/* Interface IDeckLinkInputCallback - Frame arrival callback. */
+
+[
+    object,
+    uuid(31D28EE7-88B6-4CB1-897A-CDBF79A26414),
+    helpstring("Frame arrival callback.")
+] interface IDeckLinkInputCallback_v7_6 : IUnknown
+{
+    HRESULT VideoInputFormatChanged([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode_v7_6 *newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags);
+    HRESULT VideoInputFrameArrived([in] IDeckLinkVideoInputFrame_v7_6* videoFrame, [in] IDeckLinkAudioInputPacket* audioPacket);
+};
+
+
+/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */
+
+[
+    object,
+    uuid(455D741F-1779-4800-86F5-0B5D13D79751),
+    helpstring("enumerates over supported input/output display modes.")
+] interface IDeckLinkDisplayModeIterator_v7_6 : IUnknown
+{
+    HRESULT Next([out] IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode);
+};
+
+
+/* Interface IDeckLinkDisplayMode - represents a display mode */
+
+[
+    object,
+    uuid(87451E84-2B7E-439E-A629-4393EA4A8550),
+    helpstring("represents a display mode")
+] interface IDeckLinkDisplayMode_v7_6 : IUnknown
+{
+    HRESULT GetName([out] BSTR *name);
+    BMDDisplayMode GetDisplayMode(void);
+    long GetWidth(void);
+    long GetHeight(void);
+    HRESULT GetFrameRate([out] BMDTimeValue *frameDuration, [out] BMDTimeScale *timeScale);
+    BMDFieldDominance GetFieldDominance(void);
+};
+
+
+/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */
+
+[
+    object,
+    uuid(29228142-EB8C-4141-A621-F74026450955),
+    local, 
+    helpstring("Created by QueryInterface from IDeckLink.")
+] interface IDeckLinkOutput_v7_6 : IUnknown
+{
+    HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);
+
+    /* Video Output */
+
+    HRESULT EnableVideoOutput(BMDDisplayMode displayMode, BMDVideoOutputFlags flags);
+    HRESULT DisableVideoOutput(void);
+
+    HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator);
+    HRESULT CreateVideoFrame(long width, long height, long rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame_v7_6 **outFrame);
+    HRESULT CreateAncillaryData(BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer);
+
+    HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame_v7_6 *theFrame);
+    HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale);
+    HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback_v7_6 *theCallback);
+    HRESULT GetBufferedVideoFrameCount([out] unsigned long *bufferedFrameCount);
+
+    /* Audio Output */
+
+    HRESULT EnableAudioOutput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount, BMDAudioOutputStreamType streamType);
+    HRESULT DisableAudioOutput(void);
+
+    HRESULT WriteAudioSamplesSync([in] void *buffer, unsigned long sampleFrameCount, [out] unsigned long *sampleFramesWritten);
+
+    HRESULT BeginAudioPreroll(void);
+    HRESULT EndAudioPreroll(void);
+    HRESULT ScheduleAudioSamples([in] void *buffer, unsigned long sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned long *sampleFramesWritten);
+
+    HRESULT GetBufferedAudioSampleFrameCount([out] unsigned long *bufferedSampleFrameCount);
+    HRESULT FlushBufferedAudioSamples(void);
+
+    HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback);
+
+    /* Output Control */
+
+    HRESULT StartScheduledPlayback(BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed);
+    HRESULT StopScheduledPlayback(BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, BMDTimeScale timeScale);
+    HRESULT IsScheduledPlaybackRunning([out] BOOL *active);
+    HRESULT GetScheduledStreamTime(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *streamTime, [out] double *playbackSpeed);
+
+    /* Hardware Timing */
+
+    HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame);
+};
+
+
+/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */
+
+[
+    object,
+    uuid(300C135A-9F43-48E2-9906-6D7911D93CF1),
+    helpstring("Created by QueryInterface from IDeckLink.")
+] interface IDeckLinkInput_v7_6 : IUnknown
+{
+    HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport *result);
+    HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+    HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);
+
+    /* Video Input */
+
+    HRESULT EnableVideoInput(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags);
+    HRESULT DisableVideoInput(void);
+    HRESULT GetAvailableVideoFrameCount([out] unsigned long *availableFrameCount);
+
+    /* Audio Input */
+
+    HRESULT EnableAudioInput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned long channelCount);
+    HRESULT DisableAudioInput(void);
+    HRESULT GetAvailableAudioSampleFrameCount([out] unsigned long *availableSampleFrameCount);
+
+    /* Input Control */
+
+    HRESULT StartStreams(void);
+    HRESULT StopStreams(void);
+    HRESULT PauseStreams(void);
+    HRESULT FlushStreams(void);
+    HRESULT SetCallback([in] IDeckLinkInputCallback_v7_6 *theCallback);
+
+    /* Hardware Timing */
+
+    HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame);
+};
+
+
+/* Interface IDeckLinkTimecode_v7_6 - Used for video frame timecode representation. */
+
+[
+    object,
+    uuid(EFB9BCA6-A521-44F7-BD69-2332F24D9EE6),
+    helpstring("Used for video frame timecode representation.")
+] interface IDeckLinkTimecode_v7_6 : IUnknown
+{
+    BMDTimecodeBCD GetBCD(void);
+    HRESULT GetComponents([out] unsigned char *hours, [out] unsigned char *minutes, [out] unsigned char *seconds, [out] unsigned char *frames);
+    HRESULT GetString([out] BSTR *timecode);
+    BMDTimecodeFlags GetFlags(void);
+};
+
+
+/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */
+
+[
+    object,
+    uuid(A8D8238E-6B18-4196-99E1-5AF717B83D32),
+    local, 
+    helpstring("Interface to encapsulate a video frame; can be caller-implemented.")
+] interface IDeckLinkVideoFrame_v7_6 : IUnknown
+{
+    long GetWidth(void);
+    long GetHeight(void);
+    long GetRowBytes(void);
+    BMDPixelFormat GetPixelFormat(void);
+    BMDFrameFlags GetFlags(void);
+    HRESULT GetBytes([out] void **buffer);
+
+    HRESULT GetTimecode(BMDTimecodeFormat format, [out] IDeckLinkTimecode_v7_6 **timecode);
+    HRESULT GetAncillaryData([out] IDeckLinkVideoFrameAncillary **ancillary);
+};
+
+
+/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */
+
+[
+    object,
+    uuid(46FCEE00-B4E6-43D0-91C0-023A7FCEB34F),
+    local, 
+    helpstring("Created by IDeckLinkOutput::CreateVideoFrame.")
+] interface IDeckLinkMutableVideoFrame_v7_6 : IDeckLinkVideoFrame_v7_6
+{
+    HRESULT SetFlags(BMDFrameFlags newFlags);
+
+    HRESULT SetTimecode(BMDTimecodeFormat format, [in] IDeckLinkTimecode_v7_6 *timecode);
+    HRESULT SetTimecodeFromComponents(BMDTimecodeFormat format, unsigned char hours, unsigned char minutes, unsigned char seconds, unsigned char frames, BMDTimecodeFlags flags);
+    HRESULT SetAncillaryData([in] IDeckLinkVideoFrameAncillary *ancillary);
+};
+
+
+/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */
+
+[
+    object,
+    uuid(9A74FA41-AE9F-47AC-8CF4-01F42DD59965),
+    local, 
+    helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.")
+] interface IDeckLinkVideoInputFrame_v7_6 : IDeckLinkVideoFrame_v7_6
+{
+    HRESULT GetStreamTime([out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration, BMDTimeScale timeScale);
+    HRESULT GetHardwareReferenceTimestamp(BMDTimeScale timeScale, [out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration);
+};
+
+
+/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */
+
+[
+    object,
+    uuid(373F499D-4B4D-4518-AD22-6354E5A5825E),
+    local, 
+    helpstring("Screen preview callback")
+] interface IDeckLinkScreenPreviewCallback_v7_6 : IUnknown
+{
+    HRESULT DrawFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame);
+};
+
+
+/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */
+
+[
+    object,
+    uuid(BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA),
+    local, 
+    helpstring("Created with CoCreateInstance().")
+] interface IDeckLinkGLScreenPreviewHelper_v7_6 : IUnknown
+{
+
+    /* Methods must be called with OpenGL context set */
+
+    HRESULT InitializeGL(void);
+    HRESULT PaintGL(void);
+    HRESULT SetFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame);
+};
+
+
+/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */
+
+[
+    object,
+    uuid(3EB504C9-F97D-40FE-A158-D407D48CB53B),
+    local, 
+    helpstring("Created with CoCreateInstance().")
+] interface IDeckLinkVideoConversion_v7_6 : IUnknown
+{
+    HRESULT ConvertFrame([in] IDeckLinkVideoFrame_v7_6* srcFrame, [in] IDeckLinkVideoFrame_v7_6* dstFrame);
+};
+
+/* Interface IDeckLinkConfiguration_v7_6 - Created by QueryInterface from IDeckLink. */
+
+[
+    object,
+    uuid(B8EAD569-B764-47F0-A73F-AE40DF6CBF10),
+    helpstring("Created by QueryInterface from IDeckLink.")
+] interface IDeckLinkConfiguration_v7_6 : IUnknown
+{
+    HRESULT GetConfigurationValidator([out] IDeckLinkConfiguration_v7_6 **configObject);
+    HRESULT WriteConfigurationToPreferences(void);
+
+    /* Video Output Configuration */
+
+    HRESULT SetVideoOutputFormat([in] BMDVideoConnection_v7_6 videoOutputConnection);
+    HRESULT IsVideoOutputActive([in] BMDVideoConnection_v7_6 videoOutputConnection, [out] BOOL *active);
+
+    HRESULT SetAnalogVideoOutputFlags([in] BMDAnalogVideoFlags analogVideoFlags);
+    HRESULT GetAnalogVideoOutputFlags([out] BMDAnalogVideoFlags *analogVideoFlags);
+
+    HRESULT EnableFieldFlickerRemovalWhenPaused([in] BOOL enable);
+    HRESULT IsEnabledFieldFlickerRemovalWhenPaused([out] BOOL *enabled);
+
+    HRESULT Set444And3GBpsVideoOutput([in] BOOL enable444VideoOutput, [in] BOOL enable3GbsOutput);
+    HRESULT Get444And3GBpsVideoOutput([out] BOOL *is444VideoOutputEnabled, [out] BOOL *threeGbsOutputEnabled);
+
+    HRESULT SetVideoOutputConversionMode([in] BMDVideoOutputConversionMode conversionMode);
+    HRESULT GetVideoOutputConversionMode([out] BMDVideoOutputConversionMode *conversionMode);
+
+    HRESULT Set_HD1080p24_to_HD1080i5994_Conversion([in] BOOL enable);
+    HRESULT Get_HD1080p24_to_HD1080i5994_Conversion([out] BOOL *enabled);
+
+    /* Video Input Configuration */
+
+    HRESULT SetVideoInputFormat([in] BMDVideoConnection_v7_6 videoInputFormat);
+    HRESULT GetVideoInputFormat([out] BMDVideoConnection_v7_6 *videoInputFormat);
+
+    HRESULT SetAnalogVideoInputFlags([in] BMDAnalogVideoFlags analogVideoFlags);
+    HRESULT GetAnalogVideoInputFlags([out] BMDAnalogVideoFlags *analogVideoFlags);
+
+    HRESULT SetVideoInputConversionMode([in] BMDVideoInputConversionMode conversionMode);
+    HRESULT GetVideoInputConversionMode([out] BMDVideoInputConversionMode *conversionMode);
+
+    HRESULT SetBlackVideoOutputDuringCapture([in] BOOL blackOutInCapture);
+    HRESULT GetBlackVideoOutputDuringCapture([out] BOOL *blackOutInCapture);
+
+    HRESULT Set32PulldownSequenceInitialTimecodeFrame([in] unsigned long aFrameTimecode);
+    HRESULT Get32PulldownSequenceInitialTimecodeFrame([out] unsigned long *aFrameTimecode);
+
+    HRESULT SetVancSourceLineMapping([in] unsigned long activeLine1VANCsource, [in] unsigned long activeLine2VANCsource, [in] unsigned long activeLine3VANCsource);
+    HRESULT GetVancSourceLineMapping([out] unsigned long *activeLine1VANCsource, [out] unsigned long *activeLine2VANCsource, [out] unsigned long *activeLine3VANCsource);
+
+    /* Audio Input Configuration */
+
+    HRESULT SetAudioInputFormat([in] BMDAudioConnection audioInputFormat);
+    HRESULT GetAudioInputFormat([out] BMDAudioConnection *audioInputFormat);
+};
+
+
+
+/* Coclasses */
+
+importlib("stdole2.tlb");
+
+[
+    uuid(D398CEE7-4434-4CA3-9BA6-5AE34556B905),
+    helpstring("CDeckLinkGLScreenPreviewHelper Class (DeckLink API v7.6)")
+] coclass CDeckLinkGLScreenPreviewHelper_v7_6
+{
+    [default] interface IDeckLinkGLScreenPreviewHelper_v7_6;
+};
+
+[
+    uuid(FFA84F77-73BE-4FB7-B03E-B5E44B9F759B),
+    helpstring("CDeckLinkVideoConversion Class (DeckLink API v7.6)")
+] coclass CDeckLinkVideoConversion_v7_6
+{
+    [default] interface IDeckLinkVideoConversion_v7_6;
+};
+
diff --git a/modules/decklink/interop/DeckLinkAPI_v7_9.idl b/modules/decklink/interop/DeckLinkAPI_v7_9.idl
new file mode 100644 (file)
index 0000000..5e57b14
--- /dev/null
@@ -0,0 +1,69 @@
+/* -LICENSE-START-
+** Copyright (c) 2010 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+** 
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+** 
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+/* DeckLinkAPI_v7_9.idl */
+
+/* Interface IDeckLinkDeckControl_v7_9 - Deck Control main interface */
+
+[
+       object,
+       uuid(A4D81043-0619-42B7-8ED6-602D29041DF7),
+       helpstring("Deck Control main interface")
+] interface IDeckLinkDeckControl_v7_9 : IUnknown
+{
+       HRESULT Open([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError *error);
+       HRESULT Close([in] BOOL standbyOn);
+       HRESULT GetCurrentState([out] BMDDeckControlMode *mode, [out] BMDDeckControlVTRControlState *vtrControlState, [out] BMDDeckControlStatusFlags *flags);
+       HRESULT SetStandby([in] BOOL standbyOn);
+       HRESULT Play([out] BMDDeckControlError *error);
+       HRESULT Stop([out] BMDDeckControlError *error);
+       HRESULT TogglePlayStop([out] BMDDeckControlError *error);
+       HRESULT Eject([out] BMDDeckControlError *error);
+       HRESULT GoToTimecode([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError *error);
+       HRESULT FastForward([in] BOOL viewTape, [out] BMDDeckControlError *error);
+       HRESULT Rewind([in] BOOL viewTape, [out] BMDDeckControlError *error);
+       HRESULT StepForward([out] BMDDeckControlError *error);
+       HRESULT StepBack([out] BMDDeckControlError *error);
+       HRESULT Jog([in] double rate, [out] BMDDeckControlError *error);
+       HRESULT Shuttle([in] double rate, [out] BMDDeckControlError *error);
+       HRESULT GetTimecodeString([out] BSTR *currentTimeCode, [out] BMDDeckControlError *error);
+       HRESULT GetTimecode([out] IDeckLinkTimecode **currentTimecode, [out] BMDDeckControlError *error);
+       HRESULT GetTimecodeBCD([out] BMDTimecodeBCD *currentTimecode, [out] BMDDeckControlError *error);
+       HRESULT SetPreroll([in] unsigned long prerollSeconds);
+       HRESULT GetPreroll([out] unsigned long *prerollSeconds);
+       HRESULT SetExportOffset([in] long exportOffsetFields);
+       HRESULT GetExportOffset([out] long *exportOffsetFields);
+       HRESULT GetManualExportOffset([out] long *deckManualExportOffsetFields);
+       HRESULT SetCaptureOffset([in] long captureOffsetFields);
+       HRESULT GetCaptureOffset([out] long *captureOffsetFields);
+       HRESULT StartExport([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError *error);
+       HRESULT StartCapture([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError *error);
+       HRESULT GetDeviceID([out] unsigned short *deviceId, [out] BMDDeckControlError *error);
+       HRESULT Abort(void);
+       HRESULT CrashRecordStart([out] BMDDeckControlError *error);
+       HRESULT CrashRecordStop([out] BMDDeckControlError *error);
+       HRESULT SetCallback([in] IDeckLinkDeckControlStatusCallback *callback);
+};
diff --git a/modules/decklink/producer/decklink_producer.cpp b/modules/decklink/producer/decklink_producer.cpp
new file mode 100644 (file)
index 0000000..2723a64
--- /dev/null
@@ -0,0 +1,349 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "decklink_producer.h"\r
+\r
+#include "../interop/DeckLinkAPI_h.h"\r
+#include "../util/util.h"\r
+\r
+#include "../../ffmpeg/producer/filter/filter.h"\r
+#include "../../ffmpeg/producer/util/util.h"\r
+#include "../../ffmpeg/producer/muxer/frame_muxer.h"\r
+#include "../../ffmpeg/producer/muxer/display_mode.h"\r
+\r
+#include <common/concurrency/com_context.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/log/log.h>\r
+#include <common/memory/memclr.h>\r
+#include <common/utility/param.h>\r
+\r
+#include <core/mixer/write_frame.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/timer.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavcodec/avcodec.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable : 4996)\r
+\r
+       #include <atlbase.h>\r
+\r
+       #include <atlcom.h>\r
+       #include <atlhost.h>\r
+\r
+#pragma warning(push)\r
+\r
+#include <functional>\r
+\r
+namespace caspar { namespace decklink {\r
+               \r
+class decklink_producer : boost::noncopyable, public IDeckLinkInputCallback\r
+{      \r
+       safe_ptr<diagnostics::graph>                                                            graph_;\r
+       boost::timer                                                                                            tick_timer_;\r
+       boost::timer                                                                                            frame_timer_;\r
+\r
+       CComPtr<IDeckLink>                                                                                      decklink_;\r
+       CComQIPtr<IDeckLinkInput>                                                                       input_;\r
+       CComQIPtr<IDeckLinkAttributes >                                                         attributes_;\r
+       \r
+       const std::wstring                                                                                      model_name_;\r
+       const size_t                                                                                            device_index_;\r
+       const std::wstring                                                                                      filter_;\r
+       \r
+       core::video_format_desc                                                                         format_desc_;\r
+       std::vector<size_t>                                                                                     audio_cadence_;\r
+       boost::circular_buffer<size_t>                                                          sync_buffer_;\r
+       ffmpeg::frame_muxer                                                                                     muxer_;\r
+                       \r
+       tbb::atomic<int>                                                                                        hints_;\r
+       safe_ptr<core::frame_factory>                                                           frame_factory_;\r
+\r
+       tbb::concurrent_bounded_queue<safe_ptr<core::basic_frame>>      frame_buffer_;\r
+\r
+       std::exception_ptr                                                                                      exception_;             \r
+\r
+public:\r
+       decklink_producer(const core::video_format_desc& format_desc, size_t device_index, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filter, std::size_t buffer_depth)\r
+               : decklink_(get_device(device_index))\r
+               , input_(decklink_)\r
+               , attributes_(decklink_)\r
+               , model_name_(get_model_name(decklink_))\r
+               , device_index_(device_index)\r
+               , filter_(filter)\r
+               , format_desc_(format_desc)\r
+               , audio_cadence_(format_desc.audio_cadence)\r
+               , muxer_(format_desc.fps, frame_factory, false, filter)\r
+               , sync_buffer_(format_desc.audio_cadence.size())\r
+               , frame_factory_(frame_factory)\r
+       {               \r
+               hints_ = 0;\r
+               frame_buffer_.set_capacity(buffer_depth);\r
+               \r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
+               graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+               graph_->set_color("output-buffer", diagnostics::color(0.0f, 1.0f, 0.0f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+               \r
+               auto display_mode = get_display_mode(input_, format_desc_.format, bmdFormat8BitYUV, bmdVideoInputFlagDefault);\r
+                               \r
+               // NOTE: bmdFormat8BitARGB is currently not supported by any decklink card. (2011-05-08)\r
+               if(FAILED(input_->EnableVideoInput(display_mode, bmdFormat8BitYUV, bmdVideoInputFlagDefault))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() \r
+                                                                       << msg_info(narrow(print()) + " Could not enable video input.")\r
+                                                                       << boost::errinfo_api_function("EnableVideoInput"));\r
+\r
+               if(FAILED(input_->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, format_desc_.audio_channels))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() \r
+                                                                       << msg_info(narrow(print()) + " Could not enable audio input.")\r
+                                                                       << boost::errinfo_api_function("EnableAudioInput"));\r
+                       \r
+               if (FAILED(input_->SetCallback(this)) != S_OK)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() \r
+                                                                       << msg_info(narrow(print()) + " Failed to set input callback.")\r
+                                                                       << boost::errinfo_api_function("SetCallback"));\r
+                       \r
+               if(FAILED(input_->StartStreams()))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() \r
+                                                                       << msg_info(narrow(print()) + " Failed to start input stream.")\r
+                                                                       << boost::errinfo_api_function("StartStreams"));\r
+       }\r
+\r
+       ~decklink_producer()\r
+       {\r
+               if(input_ != nullptr) \r
+               {\r
+                       input_->StopStreams();\r
+                       input_->DisableVideoInput();\r
+               }\r
+       }\r
+\r
+       virtual HRESULT STDMETHODCALLTYPE       QueryInterface (REFIID, LPVOID*)        {return E_NOINTERFACE;}\r
+       virtual ULONG STDMETHODCALLTYPE         AddRef ()                                                       {return 1;}\r
+       virtual ULONG STDMETHODCALLTYPE         Release ()                                                      {return 1;}\r
+               \r
+       virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents notificationEvents, IDeckLinkDisplayMode* newDisplayMode, BMDDetectedVideoInputFormatFlags /*detectedSignalFlags*/)\r
+       {\r
+               return S_OK;\r
+       }\r
+\r
+       virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* audio)\r
+       {       \r
+               if(!video)\r
+                       return S_OK;\r
+\r
+               try\r
+               {\r
+                       graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
+                       tick_timer_.restart();\r
+\r
+                       frame_timer_.restart();\r
+\r
+                       // PUSH\r
+\r
+                       void* bytes = nullptr;\r
+                       if(FAILED(video->GetBytes(&bytes)) || !bytes)\r
+                               return S_OK;\r
+                       \r
+                       safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);     \r
+                       avcodec_get_frame_defaults(av_frame.get());\r
+                                               \r
+                       av_frame->data[0]                       = reinterpret_cast<uint8_t*>(bytes);\r
+                       av_frame->linesize[0]           = video->GetRowBytes();                 \r
+                       av_frame->format                        = PIX_FMT_UYVY422;\r
+                       av_frame->width                         = video->GetWidth();\r
+                       av_frame->height                        = video->GetHeight();\r
+                       av_frame->interlaced_frame      = format_desc_.field_mode != core::field_mode::progressive;\r
+                       av_frame->top_field_first       = format_desc_.field_mode == core::field_mode::upper ? 1 : 0;\r
+                               \r
+                       std::shared_ptr<core::audio_buffer> audio_buffer;\r
+\r
+                       // It is assumed that audio is always equal or ahead of video.\r
+                       if(audio && SUCCEEDED(audio->GetBytes(&bytes)) && bytes)\r
+                       {\r
+                               auto sample_frame_count = audio->GetSampleFrameCount();\r
+                               auto audio_data = reinterpret_cast<int32_t*>(bytes);\r
+                               audio_buffer = std::make_shared<core::audio_buffer>(audio_data, audio_data + sample_frame_count*format_desc_.audio_channels);\r
+                       }\r
+                       else                    \r
+                               audio_buffer = std::make_shared<core::audio_buffer>(audio_cadence_.front(), 0);\r
+                       \r
+                       // Note: Uses 1 step rotated cadence for 1001 modes (1602, 1602, 1601, 1602, 1601)\r
+                       // This cadence fills the audio mixer most optimally.\r
+\r
+                       sync_buffer_.push_back(audio_buffer->size());           \r
+                       if(!boost::range::equal(sync_buffer_, audio_cadence_))\r
+                       {\r
+                               CASPAR_LOG(trace) << print() << L" Syncing audio.";\r
+                               return S_OK;\r
+                       }\r
+\r
+                       muxer_.push(audio_buffer);\r
+                       muxer_.push(av_frame, hints_);  \r
+                                                                                       \r
+                       boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+                       \r
+                       // POLL\r
+                       \r
+                       for(auto frame = muxer_.poll(); frame; frame = muxer_.poll())\r
+                       {\r
+                               if(!frame_buffer_.try_push(make_safe_ptr(frame)))\r
+                               {\r
+                                       auto dummy = core::basic_frame::empty();\r
+                                       frame_buffer_.try_pop(dummy);\r
+\r
+                                       frame_buffer_.try_push(make_safe_ptr(frame));\r
+\r
+                                       graph_->set_tag("dropped-frame");\r
+                               }\r
+                       }\r
+\r
+                       graph_->set_value("frame-time", frame_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+                       graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));      \r
+               }\r
+               catch(...)\r
+               {\r
+                       exception_ = std::current_exception();\r
+                       return E_FAIL;\r
+               }\r
+\r
+               return S_OK;\r
+       }\r
+       \r
+       safe_ptr<core::basic_frame> get_frame(int hints)\r
+       {\r
+               if(exception_ != nullptr)\r
+                       std::rethrow_exception(exception_);\r
+\r
+               hints_ = hints;\r
+\r
+               safe_ptr<core::basic_frame> frame = core::basic_frame::late();\r
+               if(!frame_buffer_.try_pop(frame))\r
+                       graph_->set_tag("late-frame");\r
+               graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));      \r
+               return frame;\r
+       }\r
+       \r
+       std::wstring print() const\r
+       {\r
+               return model_name_ + L" [" + boost::lexical_cast<std::wstring>(device_index_) + L"|" + format_desc_.name + L"]";\r
+       }\r
+};\r
+       \r
+class decklink_producer_proxy : public core::frame_producer\r
+{              \r
+       safe_ptr<core::basic_frame>             last_frame_;\r
+       com_context<decklink_producer>  context_;\r
+       const uint32_t                                  length_;\r
+public:\r
+\r
+       explicit decklink_producer_proxy(const safe_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, size_t device_index, const std::wstring& filter_str, uint32_t length, std::size_t buffer_depth)\r
+               : context_(L"decklink_producer[" + boost::lexical_cast<std::wstring>(device_index) + L"]")\r
+               , last_frame_(core::basic_frame::empty())\r
+               , length_(length)\r
+       {\r
+               context_.reset([&]{return new decklink_producer(format_desc, device_index, frame_factory, filter_str, buffer_depth);}); \r
+       }\r
+       \r
+       // frame_producer\r
+                               \r
+       virtual safe_ptr<core::basic_frame> receive(int hints) override\r
+       {\r
+               auto frame = context_->get_frame(hints);\r
+               if(frame != core::basic_frame::late())\r
+                       last_frame_ = frame;\r
+               return frame;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return disable_audio(last_frame_);\r
+       }\r
+       \r
+       virtual uint32_t nb_frames() const override\r
+       {\r
+               return length_;\r
+       }\r
+       \r
+       std::wstring print() const override\r
+       {\r
+               return context_->print();\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"decklink-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       if(params.empty() || !boost::iequals(params[0], "decklink"))\r
+               return core::frame_producer::empty();\r
+\r
+       auto device_index       = get_param(L"DEVICE", params, -1);\r
+       if(device_index == -1)\r
+               device_index = boost::lexical_cast<int>(params.at(1));\r
+       auto filter_str         = get_param(L"FILTER", params);         \r
+       auto length                     = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max());   \r
+       auto buffer_depth       = get_param(L"BUFFER", params, 2);      \r
+       auto format_desc        = core::video_format_desc::get(get_param(L"FORMAT", params, L"INVALID"));\r
+       \r
+       boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
+       boost::replace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1");\r
+       \r
+       if(format_desc.format == core::video_format::invalid)\r
+               format_desc = frame_factory->get_video_format_desc();\r
+                       \r
+       return create_producer_print_proxy(\r
+                  create_producer_destroy_proxy(\r
+                       make_safe<decklink_producer_proxy>(frame_factory, format_desc, device_index, filter_str, length, buffer_depth)));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/decklink/producer/decklink_producer.h b/modules/decklink/producer/decklink_producer.h
new file mode 100644 (file)
index 0000000..a190ec5
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace decklink {\r
+       \r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}\r
diff --git a/modules/decklink/util/util.h b/modules/decklink/util/util.h
new file mode 100644 (file)
index 0000000..e8b4329
--- /dev/null
@@ -0,0 +1,165 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/log/log.h>\r
+#include <core/video_format.h>\r
+\r
+#include "../interop/DeckLinkAPI_h.h"\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#include <atlbase.h>\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace decklink {\r
+       \r
+static BMDDisplayMode get_decklink_video_format(core::video_format::type fmt) \r
+{\r
+       switch(fmt)\r
+       {\r
+       case core::video_format::pal:                   return bmdModePAL;\r
+       case core::video_format::ntsc:                  return bmdModeNTSC;\r
+       case core::video_format::x576p2500:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p2398:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p2400:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p2500:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p5000:             return bmdModeHD720p50;\r
+       case core::video_format::x720p2997:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p5994:             return bmdModeHD720p5994;\r
+       case core::video_format::x720p3000:             return (BMDDisplayMode)ULONG_MAX;\r
+       case core::video_format::x720p6000:             return bmdModeHD720p60;\r
+       case core::video_format::x1080p2398:    return bmdModeHD1080p2398;\r
+       case core::video_format::x1080p2400:    return bmdModeHD1080p24;\r
+       case core::video_format::x1080i5000:    return bmdModeHD1080i50;\r
+       case core::video_format::x1080i5994:    return bmdModeHD1080i5994;\r
+       case core::video_format::x1080i6000:    return bmdModeHD1080i6000;\r
+       case core::video_format::x1080p2500:    return bmdModeHD1080p25;\r
+       case core::video_format::x1080p2997:    return bmdModeHD1080p2997;\r
+       case core::video_format::x1080p3000:    return bmdModeHD1080p30;\r
+       case core::video_format::x1080p5000:    return bmdModeHD1080p50;\r
+       case core::video_format::x1080p5994:    return bmdModeHD1080p5994;\r
+       case core::video_format::x1080p6000:    return bmdModeHD1080p6000;\r
+       default:                                                                return (BMDDisplayMode)ULONG_MAX;\r
+       }\r
+}\r
+\r
+static core::video_format::type get_caspar_video_format(BMDDisplayMode fmt) \r
+{\r
+       switch(fmt)\r
+       {\r
+       case bmdModePAL:                                                return core::video_format::pal;         \r
+       case bmdModeNTSC:                                               return core::video_format::ntsc;                \r
+       case bmdModeHD720p50:                                   return core::video_format::x720p5000;   \r
+       case bmdModeHD720p5994:                                 return core::video_format::x720p5994;   \r
+       case bmdModeHD720p60:                                   return core::video_format::x720p6000;   \r
+       case bmdModeHD1080p2398:                                return core::video_format::x1080p2398;  \r
+       case bmdModeHD1080p24:                                  return core::video_format::x1080p2400;  \r
+       case bmdModeHD1080i50:                                  return core::video_format::x1080i5000;  \r
+       case bmdModeHD1080i5994:                                return core::video_format::x1080i5994;  \r
+       case bmdModeHD1080i6000:                                return core::video_format::x1080i6000;  \r
+       case bmdModeHD1080p25:                                  return core::video_format::x1080p2500;  \r
+       case bmdModeHD1080p2997:                                return core::video_format::x1080p2997;  \r
+       case bmdModeHD1080p30:                                  return core::video_format::x1080p3000;  \r
+       case bmdModeHD1080p50:                                  return core::video_format::x1080p5000;  \r
+       case bmdModeHD1080p5994:                                return core::video_format::x1080p5994;  \r
+       case bmdModeHD1080p6000:                                return core::video_format::x1080p6000;  \r
+       default:                                                                return core::video_format::invalid;     \r
+       }\r
+}\r
+\r
+template<typename T, typename F>\r
+BMDDisplayMode get_display_mode(const T& device, BMDDisplayMode format, BMDPixelFormat pix_fmt, F flag)\r
+{\r
+       CComPtr<IDeckLinkDisplayModeIterator> iterator;\r
+       CComPtr<IDeckLinkDisplayMode>             mode;\r
+       \r
+       if(SUCCEEDED(device->GetDisplayModeIterator(&iterator)))\r
+       {\r
+               while(SUCCEEDED(iterator->Next(&mode)) && \r
+                               mode != nullptr && \r
+                               mode->GetDisplayMode() != format){}\r
+       }\r
+\r
+       if(!mode)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Device could not find requested video-format.") \r
+                                                                                                << arg_value_info(boost::lexical_cast<std::string>(format))\r
+                                                                                                << arg_name_info("format"));\r
+               \r
+       BMDDisplayModeSupport displayModeSupport;\r
+       if(FAILED(device->DoesSupportVideoMode(mode->GetDisplayMode(), pix_fmt, flag, &displayModeSupport, nullptr)) || displayModeSupport == bmdDisplayModeNotSupported)\r
+               CASPAR_LOG(warning) << L"Device does not support video-format: " << mode->GetDisplayMode();\r
+               //BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Device does not support requested video-format.")\r
+               //                                                                               << arg_value_info(boost::lexical_cast<std::string>(format))\r
+               //                                                                               << arg_name_info("format"));\r
+       else if(displayModeSupport == bmdDisplayModeSupportedWithConversion)\r
+               CASPAR_LOG(warning) << L"Device supports video-format with conversion: " << mode->GetDisplayMode();\r
+\r
+       return mode->GetDisplayMode();\r
+}\r
+\r
+template<typename T, typename F>\r
+static BMDDisplayMode get_display_mode(const T& device, core::video_format::type fmt, BMDPixelFormat pix_fmt, F flag)\r
+{      \r
+       return get_display_mode(device, get_decklink_video_format(fmt), pix_fmt, flag);\r
+}\r
+\r
+template<typename T>\r
+static std::wstring get_version(T& iterator)\r
+{\r
+       CComQIPtr<IDeckLinkAPIInformation> info = iterator;\r
+       if (!info)\r
+               return L"Unknown";\r
+       \r
+       BSTR ver;               \r
+       info->GetString(BMDDeckLinkAPIVersion, &ver);\r
+               \r
+       return ver;                                     \r
+}\r
+\r
+static CComPtr<IDeckLink> get_device(size_t device_index)\r
+{\r
+       CComPtr<IDeckLinkIterator> pDecklinkIterator;\r
+       if(FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink drivers not found."));\r
+               \r
+       size_t n = 0;\r
+       CComPtr<IDeckLink> decklink;\r
+       while(n < device_index && pDecklinkIterator->Next(&decklink) == S_OK){++n;}     \r
+\r
+       if(n != device_index || !decklink)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink device not found.") << arg_name_info("device_index") << arg_value_info(boost::lexical_cast<std::string>(device_index)));\r
+               \r
+       return decklink;\r
+}\r
+\r
+template <typename T>\r
+static std::wstring get_model_name(const T& device)\r
+{      \r
+       BSTR pModelName;\r
+       device->GetModelName(&pModelName);\r
+       return std::wstring(pModelName);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/StdAfx.cpp b/modules/ffmpeg/StdAfx.cpp
new file mode 100644 (file)
index 0000000..923b06b
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"\r
diff --git a/modules/ffmpeg/StdAfx.h b/modules/ffmpeg/StdAfx.h
new file mode 100644 (file)
index 0000000..f7e56ad
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#define NOMINMAX\r
+\r
+#include <memory>\r
+#include <array>\r
+#include <functional>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <deque>\r
+#include <queue>\r
+#include <string>\r
+#include <math.h>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/parallel_for.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/assign.hpp>\r
+\r
+#include <common/utility/string.h>\r
+#include <common/utility/assert.h>\r
+#include <common/memory/safe_ptr.h>\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include <common/log/log.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/exception/win32_exception.h>\r
+\r
+#pragma warning(push, 1)\r
+\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavformat/avformat.h>\r
+       #include <libavcodec/avcodec.h>\r
+       #include <libavfilter/avfilter.h>\r
+       #include <libswscale/swscale.h>\r
+}\r
+\r
+#pragma warning(pop)\r
diff --git a/modules/ffmpeg/consumer/ffmpeg_consumer.cpp b/modules/ffmpeg/consumer/ffmpeg_consumer.cpp
new file mode 100644 (file)
index 0000000..7fd57ed
--- /dev/null
@@ -0,0 +1,776 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
\r
+#include "../StdAfx.h"\r
+\r
+#include "../ffmpeg_error.h"\r
+\r
+#include "ffmpeg_consumer.h"\r
+\r
+#include "../producer/audio/audio_resampler.h"\r
+\r
+#include <core/mixer/read_frame.h>\r
+#include <core/mixer/audio/audio_util.h>\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/video_format.h>\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/concurrency/future_util.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/env.h>\r
+#include <common/utility/string.h>\r
+#include <common/utility/param.h>\r
+#include <common/memory/memshfl.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+#include <tbb/parallel_invoke.h>\r
+\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/range/algorithm_ext.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#include <string>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavformat/avformat.h>\r
+       #include <libswscale/swscale.h>\r
+       #include <libavutil/opt.h>\r
+       #include <libavutil/pixdesc.h>\r
+       #include <libavutil/parseutils.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+int av_opt_set(void *obj, const char *name, const char *val, int search_flags)\r
+{\r
+       AVClass* av_class = *(AVClass**)obj;\r
+\r
+       if((strcmp(name, "pix_fmt") == 0 || strcmp(name, "pixel_format") == 0) && strcmp(av_class->class_name, "AVCodecContext") == 0)\r
+       {\r
+               AVCodecContext* c = (AVCodecContext*)obj;               \r
+               auto pix_fmt = av_get_pix_fmt(val);\r
+               if(pix_fmt == PIX_FMT_NONE)\r
+                       return -1;              \r
+               c->pix_fmt = pix_fmt;\r
+               return 0;\r
+       }\r
+       if((strcmp(name, "r") == 0 || strcmp(name, "frame_rate") == 0) && strcmp(av_class->class_name, "AVCodecContext") == 0)\r
+       {\r
+               AVCodecContext* c = (AVCodecContext*)obj;       \r
+\r
+               if(c->codec_type != AVMEDIA_TYPE_VIDEO)\r
+                       return -1;\r
+\r
+               AVRational rate;\r
+               int ret = av_parse_video_rate(&rate, val);\r
+               if(ret < 0)\r
+                       return ret;\r
+\r
+               c->time_base.num = rate.den;\r
+               c->time_base.den = rate.num;\r
+               return 0;\r
+       }\r
+\r
+       return ::av_opt_set(obj, name, val, search_flags);\r
+}\r
+\r
+struct option\r
+{\r
+       std::string name;\r
+       std::string value;\r
+\r
+       option(std::string name, std::string value)\r
+               : name(std::move(name))\r
+               , value(std::move(value))\r
+       {\r
+       }\r
+};\r
+       \r
+struct output_format\r
+{\r
+       AVOutputFormat* format;\r
+       int                             width;\r
+       int                             height;\r
+       CodecID                 vcodec;\r
+       CodecID                 acodec;\r
+\r
+       output_format(const core::video_format_desc& format_desc, const std::string& filename, std::vector<option>& options)\r
+               : format(av_guess_format(nullptr, filename.c_str(), nullptr))\r
+               , width(format_desc.width)\r
+               , height(format_desc.height)\r
+               , vcodec(CODEC_ID_NONE)\r
+               , acodec(CODEC_ID_NONE)\r
+       {\r
+               boost::range::remove_erase_if(options, [&](const option& o)\r
+               {\r
+                       return set_opt(o.name, o.value);\r
+               });\r
+               \r
+               if(vcodec == CODEC_ID_NONE)\r
+                       vcodec = format->video_codec;\r
+\r
+               if(acodec == CODEC_ID_NONE)\r
+                       acodec = format->audio_codec;\r
+               \r
+               if(vcodec == CODEC_ID_NONE)\r
+                       vcodec = CODEC_ID_H264;\r
+               \r
+               if(acodec == CODEC_ID_NONE)\r
+                       acodec = CODEC_ID_PCM_S16LE;\r
+       }\r
+       \r
+       bool set_opt(const std::string& name, const std::string& value)\r
+       {\r
+               //if(name == "target")\r
+               //{ \r
+               //      enum { PAL, NTSC, FILM, UNKNOWN } norm = UNKNOWN;\r
+               //      \r
+               //      if(name.find("pal-") != std::string::npos)\r
+               //              norm = PAL;\r
+               //      else if(name.find("ntsc-") != std::string::npos)\r
+               //              norm = NTSC;\r
+\r
+               //      if(norm == UNKNOWN)\r
+               //              BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("target"));\r
+               //      \r
+               //      if (name.find("-dv") != std::string::npos) \r
+               //      {\r
+               //              set_opt("f", "dv");\r
+               //              set_opt("s", norm == PAL ? "720x576" : "720x480");\r
+               //              //set_opt("pix_fmt", name.find("-dv50") != std::string::npos ? "yuv422p" : norm == PAL ? "yuv420p" : "yuv411p");\r
+               //              //set_opt("ar", "48000");\r
+               //              //set_opt("ac", "2");\r
+               //      } \r
+               //}\r
+               if(name == "f")\r
+               {\r
+                       format = av_guess_format(value.c_str(), nullptr, nullptr);\r
+\r
+                       if(format == nullptr)\r
+                               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("f"));\r
+\r
+                       return true;\r
+               }\r
+               else if(name == "vcodec")\r
+               {\r
+                       auto c = avcodec_find_encoder_by_name(value.c_str());\r
+                       if(c == nullptr)\r
+                               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("vcodec"));\r
+\r
+                       vcodec = avcodec_find_encoder_by_name(value.c_str())->id;\r
+                       return true;\r
+\r
+               }\r
+               else if(name == "acodec")\r
+               {\r
+                       auto c = avcodec_find_encoder_by_name(value.c_str());\r
+                       if(c == nullptr)\r
+                               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("acodec"));\r
+\r
+                       acodec = avcodec_find_encoder_by_name(value.c_str())->id;\r
+\r
+                       return true;\r
+               }\r
+               else if(name == "s")\r
+               {\r
+                       if(av_parse_video_size(&width, &height, value.c_str()) < 0)\r
+                               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("s"));\r
+                       \r
+                       return true;\r
+               }\r
+\r
+               return false;\r
+       }\r
+};\r
+\r
+typedef std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>>    byte_vector;\r
+\r
+struct ffmpeg_consumer : boost::noncopyable\r
+{              \r
+       const std::string                                               filename_;\r
+               \r
+       const std::shared_ptr<AVFormatContext>  oc_;\r
+       const core::video_format_desc                   format_desc_;\r
+       \r
+       const safe_ptr<diagnostics::graph>              graph_;\r
+\r
+       executor                                                                encode_executor_;\r
+       \r
+       std::shared_ptr<AVStream>                               audio_st_;\r
+       std::shared_ptr<AVStream>                               video_st_;\r
+       \r
+       byte_vector                                                             audio_outbuf_;\r
+       byte_vector                                                             audio_buf_;\r
+       byte_vector                                                             video_outbuf_;\r
+       byte_vector                                                             key_picture_buf_;\r
+       byte_vector                                                             picture_buf_;\r
+       std::shared_ptr<audio_resampler>                swr_;\r
+       std::shared_ptr<SwsContext>                             sws_;\r
+\r
+       int64_t                                                                 in_frame_number_;\r
+       int64_t                                                                 out_frame_number_;\r
+\r
+       output_format                                                   output_format_;\r
+       bool                                                                    key_only_;\r
+       \r
+public:\r
+       ffmpeg_consumer(const std::string& filename, const core::video_format_desc& format_desc, std::vector<option> options, bool key_only)\r
+               : filename_(filename)\r
+               , video_outbuf_(1920*1080*8)\r
+               , audio_outbuf_(10000)\r
+               , oc_(avformat_alloc_context(), av_free)\r
+               , format_desc_(format_desc)\r
+               , encode_executor_(print())\r
+               , in_frame_number_(0)\r
+               , out_frame_number_(0)\r
+               , output_format_(format_desc, filename, options)\r
+               , key_only_(key_only)\r
+       {\r
+               // TODO: Ask stakeholders about case where file already exists.\r
+               boost::filesystem2::remove(boost::filesystem2::wpath(env::media_folder() + widen(filename))); // Delete the file if it exists\r
+\r
+               graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+\r
+               encode_executor_.set_capacity(8);\r
+\r
+               oc_->oformat = output_format_.format;\r
+                               \r
+               THROW_ON_ERROR2(av_set_parameters(oc_.get(), nullptr), "[ffmpeg_consumer]");\r
+\r
+               strcpy_s(oc_->filename, filename_.c_str());\r
+               \r
+               //  Add the audio and video streams using the default format codecs     and initialize the codecs.\r
+               auto options2 = options;\r
+               video_st_ = add_video_stream(options2);\r
+\r
+               if (!key_only)\r
+                       audio_st_ = add_audio_stream(options);\r
+                               \r
+               dump_format(oc_.get(), 0, filename_.c_str(), 1);\r
+                \r
+               // Open the output ffmpeg, if needed.\r
+               if (!(oc_->oformat->flags & AVFMT_NOFILE)) \r
+                       THROW_ON_ERROR2(avio_open(&oc_->pb, filename_.c_str(), URL_WRONLY), "[ffmpeg_consumer]");\r
+                               \r
+               THROW_ON_ERROR2(av_write_header(oc_.get()), "[ffmpeg_consumer]");\r
+\r
+               if(options.size() > 0)\r
+               {\r
+                       BOOST_FOREACH(auto& option, options)\r
+                               CASPAR_LOG(warning) << L"Invalid option: -" << widen(option.name) << L" " << widen(option.value);\r
+               }\r
+\r
+               CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
+       }\r
+\r
+       ~ffmpeg_consumer()\r
+       {    \r
+               encode_executor_.stop_execute_rest();\r
+               encode_executor_.join();\r
+\r
+               // Flush\r
+               LOG_ON_ERROR2(av_interleaved_write_frame(oc_.get(), nullptr), "[ffmpeg_consumer]");\r
+               \r
+               LOG_ON_ERROR2(av_write_trailer(oc_.get()), "[ffmpeg_consumer]");\r
+               \r
+               if (!key_only_)\r
+                       audio_st_.reset();\r
+               video_st_.reset();\r
+                         \r
+               if (!(oc_->oformat->flags & AVFMT_NOFILE)) \r
+                       LOG_ON_ERROR2(avio_close(oc_->pb), "[ffmpeg_consumer]"); // Close the output ffmpeg.\r
+\r
+               CASPAR_LOG(info) << print() << L" Successfully Uninitialized."; \r
+       }\r
+                       \r
+       std::wstring print() const\r
+       {\r
+               return L"ffmpeg[" + widen(filename_) + L"]";\r
+       }\r
+\r
+       std::shared_ptr<AVStream> add_video_stream(std::vector<option>& options)\r
+       { \r
+               if(output_format_.vcodec == CODEC_ID_NONE)\r
+                       return nullptr;\r
+\r
+               auto st = av_new_stream(oc_.get(), 0);\r
+               if (!st)                \r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Could not allocate video-stream.") << boost::errinfo_api_function("av_new_stream"));              \r
+\r
+               auto encoder = avcodec_find_encoder(output_format_.vcodec);\r
+               if (!encoder)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Codec not found."));\r
+\r
+               auto c = st->codec;\r
+\r
+               avcodec_get_context_defaults3(c, encoder);\r
+                               \r
+               c->codec_id                     = output_format_.vcodec;\r
+               c->codec_type           = AVMEDIA_TYPE_VIDEO;\r
+               c->width                        = output_format_.width;\r
+               c->height                       = output_format_.height;\r
+               c->time_base.den        = format_desc_.time_scale;\r
+               c->time_base.num        = format_desc_.duration;\r
+               c->gop_size                     = 25;\r
+               c->flags                   |= format_desc_.field_mode == core::field_mode::progressive ? 0 : (CODEC_FLAG_INTERLACED_ME | CODEC_FLAG_INTERLACED_DCT);\r
+               if(c->pix_fmt == PIX_FMT_NONE)\r
+                       c->pix_fmt = PIX_FMT_YUV420P;\r
+\r
+               if(c->codec_id == CODEC_ID_PRORES)\r
+               {                       \r
+                       c->bit_rate     = c->width < 1280 ? 63*1000000 : 220*1000000;\r
+                       c->pix_fmt      = PIX_FMT_YUV422P10;\r
+               }\r
+               else if(c->codec_id == CODEC_ID_DNXHD)\r
+               {\r
+                       if(c->width < 1280 || c->height < 720)\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Unsupported video dimensions."));\r
+\r
+                       c->bit_rate     = 220*1000000;\r
+                       c->pix_fmt      = PIX_FMT_YUV422P;\r
+               }\r
+               else if(c->codec_id == CODEC_ID_DVVIDEO)\r
+               {\r
+                       c->width = c->height == 1280 ? 960  : c->width;\r
+                       \r
+                       if(format_desc_.format == core::video_format::ntsc)\r
+                               c->pix_fmt = PIX_FMT_YUV411P;\r
+                       else if(format_desc_.format == core::video_format::pal)\r
+                               c->pix_fmt = PIX_FMT_YUV420P;\r
+                       else // dv50\r
+                               c->pix_fmt = PIX_FMT_YUV422P;\r
+                       \r
+                       if(format_desc_.duration == 1001)                       \r
+                               c->width = c->height == 1080 ? 1280 : c->width;                 \r
+                       else\r
+                               c->width = c->height == 1080 ? 1440 : c->width;                 \r
+               }\r
+               else if(c->codec_id == CODEC_ID_H264)\r
+               {                          \r
+                       c->pix_fmt = PIX_FMT_YUV420P;    \r
+                       if(options.empty())\r
+                       {\r
+                               av_opt_set(c->priv_data, "preset", "ultrafast", 0);\r
+                               av_opt_set(c->priv_data, "tune",   "fastdecode",   0);\r
+                               av_opt_set(c->priv_data, "crf",    "5",     0);\r
+                       }\r
+               }\r
+               else if(c->codec_id == CODEC_ID_QTRLE)\r
+               {\r
+                       c->pix_fmt = PIX_FMT_ARGB;\r
+               }\r
+                               \r
+               c->max_b_frames = 0; // b-frames not supported.\r
+                               \r
+               boost::range::remove_erase_if(options, [&](const option& o)\r
+               {\r
+                       return ffmpeg::av_opt_set(c, o.name.c_str(), o.value.c_str(), AV_OPT_SEARCH_CHILDREN) > -1 ||\r
+                                  ffmpeg::av_opt_set(c->priv_data, o.name.c_str(), o.value.c_str(), AV_OPT_SEARCH_CHILDREN) > -1;\r
+               });\r
+                               \r
+               if(output_format_.format->flags & AVFMT_GLOBALHEADER)\r
+                       c->flags |= CODEC_FLAG_GLOBAL_HEADER;\r
+               \r
+               c->thread_count = boost::thread::hardware_concurrency();\r
+               if(avcodec_open(c, encoder) < 0)\r
+               {\r
+                       c->thread_count = 1;\r
+                       THROW_ON_ERROR2(avcodec_open(c, encoder), "[ffmpeg_consumer]");\r
+               }\r
+\r
+               return std::shared_ptr<AVStream>(st, [](AVStream* st)\r
+               {\r
+                       LOG_ON_ERROR2(avcodec_close(st->codec), "[ffmpeg_consumer]");\r
+                       av_freep(&st->codec);\r
+                       av_freep(&st);\r
+               });\r
+       }\r
+               \r
+       std::shared_ptr<AVStream> add_audio_stream(std::vector<option>& options)\r
+       {\r
+               if(output_format_.acodec == CODEC_ID_NONE)\r
+                       return nullptr;\r
+\r
+               auto st = av_new_stream(oc_.get(), 1);\r
+               if(!st)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Could not allocate audio-stream") << boost::errinfo_api_function("av_new_stream"));               \r
+               \r
+               auto encoder = avcodec_find_encoder(output_format_.acodec);\r
+               if (!encoder)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("codec not found"));\r
+               \r
+               auto c = st->codec;\r
+\r
+               avcodec_get_context_defaults3(c, encoder);\r
+\r
+               c->codec_id                     = output_format_.acodec;\r
+               c->codec_type           = AVMEDIA_TYPE_AUDIO;\r
+               c->sample_rate          = 48000;\r
+               c->channels                     = 2;\r
+               c->sample_fmt           = SAMPLE_FMT_S16;\r
+\r
+               if(output_format_.vcodec == CODEC_ID_FLV1)              \r
+                       c->sample_rate  = 44100;                \r
+\r
+               if(output_format_.format->flags & AVFMT_GLOBALHEADER)\r
+                       c->flags |= CODEC_FLAG_GLOBAL_HEADER;\r
+                               \r
+               boost::range::remove_erase_if(options, [&](const option& o)\r
+               {\r
+                       return ffmpeg::av_opt_set(c, o.name.c_str(), o.value.c_str(), AV_OPT_SEARCH_CHILDREN) > -1;\r
+               });\r
+\r
+               THROW_ON_ERROR2(avcodec_open(c, encoder), "[ffmpeg_consumer]");\r
+\r
+               return std::shared_ptr<AVStream>(st, [](AVStream* st)\r
+               {\r
+                       LOG_ON_ERROR2(avcodec_close(st->codec), "[ffmpeg_consumer]");;\r
+                       av_freep(&st->codec);\r
+                       av_freep(&st);\r
+               });\r
+       }\r
+\r
+       std::shared_ptr<AVFrame> convert_video(core::read_frame& frame, AVCodecContext* c)\r
+       {\r
+               if(!sws_) \r
+               {\r
+                       sws_.reset(sws_getContext(format_desc_.width, format_desc_.height, PIX_FMT_BGRA, c->width, c->height, c->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr), sws_freeContext);\r
+                       if (sws_ == nullptr) \r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Cannot initialize the conversion context"));\r
+               }\r
+\r
+               std::shared_ptr<AVFrame> in_frame(avcodec_alloc_frame(), av_free);\r
+               auto in_picture = reinterpret_cast<AVPicture*>(in_frame.get());\r
+\r
+               if (key_only_)\r
+               {\r
+                       key_picture_buf_.resize(frame.image_data().size());\r
+                       in_picture->linesize[0] = format_desc_.width * 4;\r
+                       in_picture->data[0] = key_picture_buf_.data();\r
+\r
+                       fast_memshfl(in_picture->data[0], frame.image_data().begin(), frame.image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+               }\r
+               else\r
+               {\r
+                       avpicture_fill(in_picture, const_cast<uint8_t*>(frame.image_data().begin()), PIX_FMT_BGRA, format_desc_.width, format_desc_.height);\r
+               }\r
+\r
+               std::shared_ptr<AVFrame> out_frame(avcodec_alloc_frame(), av_free);\r
+               picture_buf_.resize(avpicture_get_size(c->pix_fmt, c->width, c->height));\r
+               avpicture_fill(reinterpret_cast<AVPicture*>(out_frame.get()), picture_buf_.data(), c->pix_fmt, c->width, c->height);\r
+\r
+               sws_scale(sws_.get(), in_frame->data, in_frame->linesize, 0, format_desc_.height, out_frame->data, out_frame->linesize);\r
+\r
+               return out_frame;\r
+       }\r
+  \r
+       void encode_video_frame(core::read_frame& frame)\r
+       { \r
+               auto c = video_st_->codec;\r
+               \r
+               auto in_time  = static_cast<double>(in_frame_number_) / format_desc_.fps;\r
+               auto out_time = static_cast<double>(out_frame_number_) / (static_cast<double>(c->time_base.den) / static_cast<double>(c->time_base.num));\r
+               \r
+               in_frame_number_++;\r
+\r
+               if(out_time - in_time > 0.01)\r
+                       return;\r
\r
+               auto av_frame = convert_video(frame, c);\r
+               av_frame->interlaced_frame      = format_desc_.field_mode != core::field_mode::progressive;\r
+               av_frame->top_field_first       = format_desc_.field_mode == core::field_mode::upper;\r
+               av_frame->pts                           = out_frame_number_++;\r
+\r
+               int out_size = THROW_ON_ERROR2(avcodec_encode_video(c, video_outbuf_.data(), video_outbuf_.size(), av_frame.get()), "[ffmpeg_consumer]");\r
+               if(out_size == 0)\r
+                       return;\r
+                               \r
+               safe_ptr<AVPacket> pkt(new AVPacket, [](AVPacket* p)\r
+               {\r
+                       av_free_packet(p);\r
+                       delete p;\r
+               });\r
+               av_init_packet(pkt.get());\r
\r
+               if (c->coded_frame->pts != AV_NOPTS_VALUE)\r
+                       pkt->pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st_->time_base);\r
+\r
+               if(c->coded_frame->key_frame)\r
+                       pkt->flags |= AV_PKT_FLAG_KEY;\r
+\r
+               pkt->stream_index       = video_st_->index;\r
+               pkt->data                       = video_outbuf_.data();\r
+               pkt->size                       = out_size;\r
+                       \r
+               av_interleaved_write_frame(oc_.get(), pkt.get());               \r
+       }\r
+               \r
+       byte_vector convert_audio(core::read_frame& frame, AVCodecContext* c)\r
+       {\r
+               if(!swr_)               \r
+                       swr_.reset(new audio_resampler(c->channels, format_desc_.audio_channels, \r
+                                                                                  c->sample_rate, format_desc_.audio_sample_rate,\r
+                                                                                  c->sample_fmt, AV_SAMPLE_FMT_S32));\r
+               \r
+\r
+               auto audio_data = frame.audio_data();\r
+\r
+               std::vector<int8_t,  tbb::cache_aligned_allocator<int8_t>> audio_resample_buffer;\r
+               std::copy(reinterpret_cast<const uint8_t*>(audio_data.begin()), \r
+                                 reinterpret_cast<const uint8_t*>(audio_data.begin()) + audio_data.size()*4, \r
+                                 std::back_inserter(audio_resample_buffer));\r
+               \r
+               audio_resample_buffer = swr_->resample(std::move(audio_resample_buffer));\r
+               \r
+               return byte_vector(audio_resample_buffer.begin(), audio_resample_buffer.end());\r
+       }\r
+\r
+       void encode_audio_frame(core::read_frame& frame)\r
+       {                       \r
+               auto c = audio_st_->codec;\r
+\r
+               boost::range::push_back(audio_buf_, convert_audio(frame, c));\r
+               \r
+               std::size_t frame_size = c->frame_size;\r
+               auto input_audio_size = frame_size * av_get_bytes_per_sample(c->sample_fmt) * c->channels;\r
+               \r
+               while(audio_buf_.size() >= input_audio_size)\r
+               {\r
+                       safe_ptr<AVPacket> pkt(new AVPacket, [](AVPacket* p)\r
+                       {\r
+                               av_free_packet(p);\r
+                               delete p;\r
+                       });\r
+                       av_init_packet(pkt.get());\r
+\r
+                       if(frame_size > 1)\r
+                       {                                                               \r
+                               pkt->size = avcodec_encode_audio(c, audio_outbuf_.data(), audio_outbuf_.size(), reinterpret_cast<short*>(audio_buf_.data()));\r
+                               audio_buf_.erase(audio_buf_.begin(), audio_buf_.begin() + input_audio_size);\r
+                       }\r
+                       else\r
+                       {\r
+                               audio_outbuf_ = std::move(audio_buf_);          \r
+                               audio_buf_.clear();\r
+                               pkt->size = audio_outbuf_.size();\r
+                               pkt->data = audio_outbuf_.data();\r
+                       }\r
+               \r
+                       if(pkt->size == 0)\r
+                               return;\r
+\r
+                       if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)\r
+                               pkt->pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_st_->time_base);\r
+\r
+                       pkt->flags               |= AV_PKT_FLAG_KEY;\r
+                       pkt->stream_index = audio_st_->index;\r
+                       pkt->data                 = reinterpret_cast<uint8_t*>(audio_outbuf_.data());\r
+               \r
+                       av_interleaved_write_frame(oc_.get(), pkt.get());\r
+               }\r
+       }\r
+                \r
+       void send(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               encode_executor_.begin_invoke([=]\r
+               {               \r
+                       boost::timer frame_timer;\r
+\r
+                       encode_video_frame(*frame);\r
+\r
+                       if (!key_only_)\r
+                               encode_audio_frame(*frame);\r
+\r
+                       graph_->set_value("frame-time", frame_timer.elapsed()*format_desc_.fps*0.5);                    \r
+               });\r
+       }\r
+\r
+       bool ready_for_frame()\r
+       {\r
+               return encode_executor_.size() < encode_executor_.capacity();\r
+       }\r
+\r
+       void mark_dropped()\r
+       {\r
+               graph_->set_tag("dropped-frame");\r
+\r
+               // TODO: adjust PTS accordingly to make dropped frames contribute\r
+               //       to the total playing time\r
+       }\r
+};\r
+\r
+struct ffmpeg_consumer_proxy : public core::frame_consumer\r
+{\r
+       const std::wstring                              filename_;\r
+       const std::vector<option>               options_;\r
+       const bool                                              separate_key_;\r
+\r
+       std::unique_ptr<ffmpeg_consumer> consumer_;\r
+       std::unique_ptr<ffmpeg_consumer> key_only_consumer_;\r
+\r
+public:\r
+\r
+       ffmpeg_consumer_proxy(const std::wstring& filename, const std::vector<option>& options, bool separate_key_)\r
+               : filename_(filename)\r
+               , options_(options)\r
+               , separate_key_(separate_key_)\r
+       {\r
+       }\r
+       \r
+       virtual void initialize(const core::video_format_desc& format_desc, int)\r
+       {\r
+               consumer_.reset();\r
+               key_only_consumer_.reset();\r
+               consumer_.reset(new ffmpeg_consumer(narrow(filename_), format_desc, options_, false));\r
+\r
+               if (separate_key_)\r
+               {\r
+                       boost::filesystem::wpath fill_file(filename_);\r
+                       auto without_extension = fill_file.stem();\r
+                       auto key_file = env::media_folder() + without_extension + L"_A" + fill_file.extension();\r
+                       \r
+                       key_only_consumer_.reset(new ffmpeg_consumer(narrow(key_file), format_desc, options_, true));\r
+               }\r
+       }\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override\r
+       {\r
+               bool ready_for_frame = consumer_->ready_for_frame();\r
+\r
+               if (ready_for_frame && separate_key_)\r
+                       ready_for_frame = ready_for_frame && key_only_consumer_->ready_for_frame();\r
+\r
+               if (ready_for_frame)\r
+               {\r
+                       consumer_->send(frame);\r
+\r
+                       if (separate_key_)\r
+                               key_only_consumer_->send(frame);\r
+               }\r
+               else\r
+               {\r
+                       consumer_->mark_dropped();\r
+\r
+                       if (separate_key_)\r
+                               key_only_consumer_->mark_dropped();\r
+               }\r
+\r
+               return caspar::wrap_as_future(true);\r
+       }\r
+       \r
+       virtual std::wstring print() const override\r
+       {\r
+               return consumer_ ? consumer_->print() : L"[ffmpeg_consumer]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"ffmpeg-consumer");\r
+               info.add(L"filename", filename_);\r
+               info.add(L"separate_key", separate_key_);\r
+               return info;\r
+       }\r
+               \r
+       virtual bool has_synchronization_clock() const override\r
+       {\r
+               return false;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return 1;\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 200;\r
+       }\r
+};     \r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 1 || params[0] != L"FILE")\r
+               return core::frame_consumer::empty();\r
+\r
+       std::vector<std::wstring> params2 = params;\r
+       \r
+       auto filename   = (params2.size() > 1 ? params2[1] : L"");\r
+       auto separate_key_it = std::find(params2.begin(), params2.end(), L"SEPARATE_KEY");\r
+       bool separate_key = false;\r
+\r
+       if (separate_key_it != params2.end())\r
+       {\r
+               separate_key = true;\r
+               params2.erase(separate_key_it);\r
+       }\r
+                       \r
+       std::vector<option> options;\r
+       \r
+       if(params2.size() >= 3)\r
+       {\r
+               for(auto opt_it = params2.begin()+2; opt_it != params2.end();)\r
+               {\r
+                       auto name  = narrow(boost::trim_copy(boost::to_lower_copy(*opt_it++))).substr(1);\r
+                       auto value = narrow(boost::trim_copy(boost::to_lower_copy(*opt_it++)));\r
+                               \r
+                       if(value == "h264")\r
+                               value = "libx264";\r
+                       else if(value == "dvcpro")\r
+                               value = "dvvideo";\r
+\r
+                       options.push_back(option(name, value));\r
+               }\r
+       }\r
+               \r
+       return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + filename, options, separate_key);\r
+}\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree)\r
+{\r
+       auto filename           = ptree.get<std::wstring>(L"path");\r
+       auto codec                      = ptree.get(L"vcodec", L"libx264");\r
+       auto separate_key       = ptree.get(L"separate-key", false);\r
+\r
+       std::vector<option> options;\r
+       options.push_back(option("vcodec", narrow(codec)));\r
+       \r
+       return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + filename, options, separate_key);\r
+}\r
+\r
+}}\r
diff --git a/modules/ffmpeg/consumer/ffmpeg_consumer.h b/modules/ffmpeg/consumer/ffmpeg_consumer.h
new file mode 100644 (file)
index 0000000..9f27cdd
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+}\r
+\r
+namespace ffmpeg {\r
+\r
+       \r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/ffmpeg.cpp b/modules/ffmpeg/ffmpeg.cpp
new file mode 100644 (file)
index 0000000..16a1a97
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "consumer/ffmpeg_consumer.h"\r
+#include "producer/ffmpeg_producer.h"\r
+\r
+#include <common/log/log.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <tbb/recursive_mutex.h>\r
+\r
+#include <boost/thread.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4244)\r
+#pragma warning (disable : 4603)\r
+#pragma warning (disable : 4996)\r
+#endif\r
+\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavformat/avformat.h>\r
+       #include <libswscale/swscale.h>\r
+       #include <libavutil/avutil.h>\r
+       #include <libavfilter/avfilter.h>\r
+}\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+int ffmpeg_lock_callback(void **mutex, enum AVLockOp op) \r
+{ \r
+       if(!mutex)\r
+               return 0;\r
+\r
+       auto my_mutex = reinterpret_cast<tbb::recursive_mutex*>(*mutex);\r
+       \r
+       switch(op) \r
+       { \r
+               case AV_LOCK_CREATE: \r
+               { \r
+                       *mutex = new tbb::recursive_mutex(); \r
+                       break; \r
+               } \r
+               case AV_LOCK_OBTAIN: \r
+               { \r
+                       if(my_mutex)\r
+                               my_mutex->lock(); \r
+                       break; \r
+               } \r
+               case AV_LOCK_RELEASE: \r
+               { \r
+                       if(my_mutex)\r
+                               my_mutex->unlock(); \r
+                       break; \r
+               } \r
+               case AV_LOCK_DESTROY: \r
+               { \r
+                       delete my_mutex;\r
+                       *mutex = nullptr;\r
+                       break; \r
+               } \r
+       } \r
+       return 0; \r
+} \r
+\r
+static void sanitize(uint8_t *line)\r
+{\r
+    while(*line)\r
+       {\r
+        if(*line < 0x08 || (*line > 0x0D && *line < 0x20))\r
+            *line='?';\r
+        line++;\r
+    }\r
+}\r
+\r
+void log_callback(void* ptr, int level, const char* fmt, va_list vl)\r
+{\r
+    static int print_prefix=1;\r
+    static int count;\r
+    static char prev[1024];\r
+    char line[8192];\r
+    static int is_atty;\r
+    AVClass* avc= ptr ? *(AVClass**)ptr : NULL;\r
+    if(level > av_log_get_level())\r
+        return;\r
+    line[0]=0;\r
+       \r
+#undef fprintf\r
+    if(print_prefix && avc) \r
+       {\r
+        if (avc->parent_log_context_offset) \r
+               {\r
+            AVClass** parent= *(AVClass***)(((uint8_t*)ptr) + avc->parent_log_context_offset);\r
+            if(parent && *parent)\r
+                std::sprintf(line, "[%s @ %p] ", (*parent)->item_name(parent), parent);            \r
+        }\r
+        std::sprintf(line + strlen(line), "[%s @ %p] ", avc->item_name(ptr), ptr);\r
+    }\r
+\r
+    std::vsprintf(line + strlen(line), fmt, vl);\r
+\r
+    print_prefix = strlen(line) && line[strlen(line)-1] == '\n';\r
+       \r
+    //if(print_prefix && !strcmp(line, prev)){\r
+    //    count++;\r
+    //    if(is_atty==1)\r
+    //        fprintf(stderr, "    Last message repeated %d times\r", count);\r
+    //    return;\r
+    //}\r
+    //if(count>0){\r
+    //    fprintf(stderr, "    Last message repeated %d times\n", count);\r
+    //    count=0;\r
+    //}\r
+    strcpy(prev, line);\r
+    sanitize((uint8_t*)line);\r
+\r
+       int len = strlen(line);\r
+       if(len > 0)\r
+               line[len-1] = 0;\r
+       \r
+       if(level == AV_LOG_DEBUG)\r
+               CASPAR_LOG(debug) << L"[ffmpeg] " << line;\r
+       else if(level == AV_LOG_INFO)\r
+               CASPAR_LOG(info) << L"[ffmpeg] " << line;\r
+       else if(level == AV_LOG_WARNING)\r
+               CASPAR_LOG(warning) << L"[ffmpeg] " << line;\r
+       else if(level == AV_LOG_ERROR)\r
+               CASPAR_LOG(error) << L"[ffmpeg] " << line;\r
+       else if(level == AV_LOG_FATAL)\r
+               CASPAR_LOG(fatal) << L"[ffmpeg] " << line;\r
+       else\r
+               CASPAR_LOG(trace) << L"[ffmpeg] " << line;\r
+\r
+    //colored_fputs(av_clip(level>>3, 0, 6), line);\r
+}\r
+\r
+boost::thread_specific_ptr<bool>& get_disable_logging_for_thread()\r
+{\r
+       static boost::thread_specific_ptr<bool> disable_logging_for_thread;\r
+\r
+       return disable_logging_for_thread;\r
+}\r
+\r
+void disable_logging_for_thread()\r
+{\r
+       if (get_disable_logging_for_thread().get() == nullptr)\r
+               get_disable_logging_for_thread().reset(new bool); // bool value does not matter\r
+}\r
+\r
+bool is_logging_already_disabled_for_thread()\r
+{\r
+       return get_disable_logging_for_thread().get() != nullptr;\r
+}\r
+\r
+std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable)\r
+{\r
+       if (!disable || is_logging_already_disabled_for_thread())\r
+               return std::shared_ptr<void>();\r
+\r
+       disable_logging_for_thread();\r
+\r
+       return std::shared_ptr<void>(nullptr, [] (void*)\r
+       {\r
+               get_disable_logging_for_thread().release(); // Only works correctly if destructed in same thread as original caller.\r
+       });\r
+}\r
+\r
+void log_for_thread(void* ptr, int level, const char* fmt, va_list vl)\r
+{\r
+       //if (get_disable_logging_for_thread().get() == nullptr) // It does not matter what the value of the bool is\r
+               log_callback(ptr, level, fmt, vl);\r
+}\r
+\r
+//static int query_yadif_formats(AVFilterContext *ctx)\r
+//{\r
+//    static const int pix_fmts[] = {\r
+//        PIX_FMT_YUV444P,\r
+//        PIX_FMT_YUV422P,\r
+//        PIX_FMT_YUV420P,\r
+//        PIX_FMT_YUV410P,\r
+//        PIX_FMT_YUV411P,\r
+//        PIX_FMT_GRAY8,\r
+//        PIX_FMT_YUVJ444P,\r
+//        PIX_FMT_YUVJ422P,\r
+//        PIX_FMT_YUVJ420P,\r
+//        AV_NE( PIX_FMT_GRAY16BE, PIX_FMT_GRAY16LE ),\r
+//        PIX_FMT_YUV440P,\r
+//        PIX_FMT_YUVJ440P,\r
+//        AV_NE( PIX_FMT_YUV444P16BE, PIX_FMT_YUV444P16LE ),\r
+//        AV_NE( PIX_FMT_YUV422P16BE, PIX_FMT_YUV422P16LE ),\r
+//        AV_NE( PIX_FMT_YUV420P16BE, PIX_FMT_YUV420P16LE ),\r
+//        PIX_FMT_YUVA420P,\r
+//        PIX_FMT_NONE\r
+//    };\r
+//    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+//\r
+//    return 0;\r
+//}\r
+//\r
+//#pragma warning (push)\r
+//#pragma warning (disable : 4706)\r
+//void fix_yadif_filter_format_query()\r
+//{\r
+//     AVFilter** filter = nullptr;\r
+//    while((filter = av_filter_next(filter)) && *filter)\r
+//     {\r
+//             if(strstr((*filter)->name, "yadif") != 0)\r
+//                     (*filter)->query_formats = query_yadif_formats;\r
+//     }\r
+//}\r
+//#pragma warning (pop)\r
+\r
+void init()\r
+{\r
+       av_lockmgr_register(ffmpeg_lock_callback);\r
+       av_log_set_callback(log_for_thread);\r
+\r
+    avfilter_register_all();\r
+       //fix_yadif_filter_format_query();\r
+       av_register_all();\r
+    avformat_network_init();\r
+       avcodec_init();\r
+    avcodec_register_all();\r
+       \r
+       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+       core::register_producer_factory(create_producer);\r
+       core::register_thumbnail_producer_factory(create_thumbnail_producer);\r
+}\r
+\r
+void uninit()\r
+{\r
+       avfilter_uninit();\r
+    avformat_network_deinit();\r
+       av_lockmgr_register(nullptr);\r
+}\r
+\r
+std::wstring make_version(unsigned int ver)\r
+{\r
+       std::wstringstream str;\r
+       str << ((ver >> 16) & 0xFF) << L"." << ((ver >> 8) & 0xFF) << L"." << ((ver >> 0) & 0xFF);\r
+       return str.str();\r
+}\r
+\r
+std::wstring get_avcodec_version()\r
+{\r
+       return make_version(avcodec_version());\r
+}\r
+\r
+std::wstring get_avformat_version()\r
+{\r
+       return make_version(avformat_version());\r
+}\r
+\r
+std::wstring get_avutil_version()\r
+{\r
+       return make_version(avutil_version());\r
+}\r
+\r
+std::wstring get_avfilter_version()\r
+{\r
+       return make_version(avfilter_version());\r
+}\r
+\r
+std::wstring get_swscale_version()\r
+{\r
+       return make_version(swscale_version());\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/ffmpeg.h b/modules/ffmpeg/ffmpeg.h
new file mode 100644 (file)
index 0000000..604802f
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+#include <memory>\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+void init();\r
+void uninit();\r
+void disable_logging_for_thread();\r
+std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable);\r
+\r
+std::wstring get_avcodec_version();\r
+std::wstring get_avformat_version();\r
+std::wstring get_avutil_version();\r
+std::wstring get_avfilter_version();\r
+std::wstring get_swscale_version();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/ffmpeg.vcxproj b/modules/ffmpeg/ffmpeg.vcxproj
new file mode 100644 (file)
index 0000000..ed5f8a1
--- /dev/null
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{F6223AF3-BE0B-4B61-8406-98922CE521C2}</ProjectGuid>\r
+    <RootNamespace>ffmpeg</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>ffmpeg</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>avformat-52.lib;avcodec-52.lib;avutil-50.lib;SWSCALE-0.lib;tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>true</GenerateMapFile>\r
+      <MapExports>true</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>avformat-52.lib;avcodec-52.lib;avutil-50.lib;SWSCALE-0.lib;tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>true</GenerateMapFile>\r
+      <MapExports>true</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\ffmpeg_consumer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="ffmpeg.cpp">\r
+      <ShowIncludes Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">false</ShowIncludes>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\audio\audio_decoder.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\audio\audio_resampler.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\ffmpeg_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\filter\filter.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\filter\parallel_yadif.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\input\input.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\muxer\frame_muxer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\tbb_avcodec.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\util\flv.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\util\util.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\video\video_decoder.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\ffmpeg_consumer.h" />\r
+    <ClInclude Include="ffmpeg.h" />\r
+    <ClInclude Include="ffmpeg_error.h" />\r
+    <ClInclude Include="producer\audio\audio_decoder.h" />\r
+    <ClInclude Include="producer\audio\audio_resampler.h" />\r
+    <ClInclude Include="producer\ffmpeg_producer.h" />\r
+    <ClInclude Include="producer\filter\filter.h" />\r
+    <ClInclude Include="producer\filter\parallel_yadif.h" />\r
+    <ClInclude Include="producer\input\input.h" />\r
+    <ClInclude Include="producer\muxer\display_mode.h" />\r
+    <ClInclude Include="producer\muxer\frame_muxer.h" />\r
+    <ClInclude Include="producer\tbb_avcodec.h" />\r
+    <ClInclude Include="producer\util\flv.h" />\r
+    <ClInclude Include="producer\util\util.h" />\r
+    <ClInclude Include="producer\video\video_decoder.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/ffmpeg/ffmpeg.vcxproj.filters b/modules/ffmpeg/ffmpeg.vcxproj.filters
new file mode 100644 (file)
index 0000000..8e2e3ad
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{c9454245-e85a-45ba-960f-203b00d18454}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{4db7d9c3-08ea-4423-a303-f18737629268}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{c5a94fd1-4552-4f6d-97cd-24e44e662e0f}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\audio">\r
+      <UniqueIdentifier>{6937307b-550f-48f8-9cc0-509de0e18ddc}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\filter">\r
+      <UniqueIdentifier>{0d46b4fa-2b19-44b7-82ea-52cbd9ad24a4}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\video">\r
+      <UniqueIdentifier>{4b0f3949-6dc5-4895-837f-4c3ef1759a90}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\util">\r
+      <UniqueIdentifier>{d6af0416-0c85-45f8-97a3-4d0560b18691}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\input">\r
+      <UniqueIdentifier>{28be54fb-eb6d-4c56-a0fa-8286ae1032bf}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer\muxer">\r
+      <UniqueIdentifier>{26599786-a0d9-4cc3-b5a4-633e9c81563a}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="producer\video\video_decoder.cpp">\r
+      <Filter>source\producer\video</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\audio\audio_decoder.cpp">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\ffmpeg_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="ffmpeg.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\filter\filter.cpp">\r
+      <Filter>source\producer\filter</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\filter\parallel_yadif.cpp">\r
+      <Filter>source\producer\filter</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\audio\audio_resampler.cpp">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\util\util.cpp">\r
+      <Filter>source\producer\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\util\flv.cpp">\r
+      <Filter>source\producer\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\input\input.cpp">\r
+      <Filter>source\producer\input</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\muxer\frame_muxer.cpp">\r
+      <Filter>source\producer\muxer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\tbb_avcodec.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\ffmpeg_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="producer\ffmpeg_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\video\video_decoder.h">\r
+      <Filter>source\producer\video</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\audio\audio_decoder.h">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="consumer\ffmpeg_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="ffmpeg_error.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="ffmpeg.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\filter\filter.h">\r
+      <Filter>source\producer\filter</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\filter\parallel_yadif.h">\r
+      <Filter>source\producer\filter</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\audio\audio_resampler.h">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\util\flv.h">\r
+      <Filter>source\producer\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\util\util.h">\r
+      <Filter>source\producer\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\input\input.h">\r
+      <Filter>source\producer\input</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\muxer\frame_muxer.h">\r
+      <Filter>source\producer\muxer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\muxer\display_mode.h">\r
+      <Filter>source\producer\muxer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\tbb_avcodec.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/ffmpeg/ffmpeg_error.h b/modules/ffmpeg/ffmpeg_error.h
new file mode 100644 (file)
index 0000000..3d7fa67
--- /dev/null
@@ -0,0 +1,185 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/string.h>\r
+\r
+#include <string>\r
+\r
+#pragma warning(push, 1)\r
+\r
+extern "C" \r
+{\r
+#include <libavutil/error.h>\r
+}\r
+\r
+#pragma warning(pop)\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+struct ffmpeg_error : virtual caspar_exception{};\r
+struct averror_bsf_not_found : virtual ffmpeg_error{};\r
+struct averror_decoder_not_found : virtual ffmpeg_error{};\r
+struct averror_demuxer_not_found : virtual ffmpeg_error{};\r
+struct averror_encoder_not_found : virtual ffmpeg_error{};\r
+struct averror_eof : virtual ffmpeg_error{};\r
+struct averror_exit : virtual ffmpeg_error{};\r
+struct averror_filter_not_found : virtual ffmpeg_error{};\r
+struct averror_muxer_not_found : virtual ffmpeg_error{};\r
+struct averror_option_not_found : virtual ffmpeg_error{};\r
+struct averror_patchwelcome : virtual ffmpeg_error{};\r
+struct averror_protocol_not_found : virtual ffmpeg_error{};\r
+struct averror_stream_not_found : virtual ffmpeg_error{};\r
+\r
+static std::string av_error_str(int errn)\r
+{\r
+       char buf[256];\r
+       memset(buf, 0, 256);\r
+       if(av_strerror(errn, buf, 256) < 0)\r
+               return "";\r
+       return std::string(buf);\r
+}\r
+\r
+static void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const char* local_func, const char* file, int line)\r
+{\r
+       if(ret >= 0)\r
+               return;\r
+\r
+       switch(ret)\r
+       {\r
+       case AVERROR_BSF_NOT_FOUND:\r
+               ::boost::exception_detail::throw_exception_(averror_bsf_not_found()<<                                                                           \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);  \r
+       case AVERROR_DECODER_NOT_FOUND:\r
+               ::boost::exception_detail::throw_exception_(averror_decoder_not_found()<<                                                                               \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_DEMUXER_NOT_FOUND:\r
+               ::boost::exception_detail::throw_exception_(averror_demuxer_not_found()<<                                                                               \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_ENCODER_NOT_FOUND:\r
+               ::boost::exception_detail::throw_exception_(averror_encoder_not_found()<<                                                                               \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);  \r
+       case AVERROR_EOF:       \r
+               ::boost::exception_detail::throw_exception_(averror_eof()<<                                                                             \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_EXIT:                              \r
+               ::boost::exception_detail::throw_exception_(averror_exit()<<                                                                            \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_FILTER_NOT_FOUND:                          \r
+               ::boost::exception_detail::throw_exception_(averror_filter_not_found()<<                                                                                \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_MUXER_NOT_FOUND:   \r
+               ::boost::exception_detail::throw_exception_(averror_muxer_not_found()<<                                                                         \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_OPTION_NOT_FOUND:  \r
+               ::boost::exception_detail::throw_exception_(averror_option_not_found()<<                                                                                \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_PATCHWELCOME:      \r
+               ::boost::exception_detail::throw_exception_(averror_patchwelcome()<<                                                                            \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_PROTOCOL_NOT_FOUND:        \r
+               ::boost::exception_detail::throw_exception_(averror_protocol_not_found()<<                                                                              \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       case AVERROR_STREAM_NOT_FOUND:\r
+               ::boost::exception_detail::throw_exception_(averror_stream_not_found()<<                                                                                \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       default:\r
+               ::boost::exception_detail::throw_exception_(ffmpeg_error()<<                                                                            \r
+                       msg_info(av_error_str(ret)) <<                                                  \r
+                       source_info(narrow(source)) <<                                          \r
+                       boost::errinfo_api_function(func) <<                                    \r
+                       boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+       }\r
+}\r
+\r
+static void throw_on_ffmpeg_error(int ret, const std::wstring& source, const char* func, const char* local_func, const char* file, int line)\r
+{\r
+       throw_on_ffmpeg_error(ret, narrow(source).c_str(), func, local_func, file, line);\r
+}\r
+\r
+\r
+//#define THROW_ON_ERROR(ret, source, func) throw_on_ffmpeg_error(ret, source, __FUNC__, __FILE__, __LINE__)\r
+\r
+#define THROW_ON_ERROR_STR_(call) #call\r
+#define THROW_ON_ERROR_STR(call) THROW_ON_ERROR_STR_(call)\r
+\r
+#define THROW_ON_ERROR(ret, func, source) \\r
+               throw_on_ffmpeg_error(ret, source, func, __FUNCTION__, __FILE__, __LINE__);             \r
+\r
+#define THROW_ON_ERROR2(call, source)                                                                          \\r
+       [&]() -> int                                                                                                                    \\r
+       {                                                                                                                                               \\r
+               int ret = call;                                                                                                         \\r
+               throw_on_ffmpeg_error(ret, source, THROW_ON_ERROR_STR(call), __FUNCTION__, __FILE__, __LINE__); \\r
+               return ret;                                                                                                                     \\r
+       }()\r
+\r
+#define LOG_ON_ERROR2(call, source)                                                                                    \\r
+       [&]() -> int                                                                                                                    \\r
+       {                                       \\r
+               int ret = -1;\\r
+               try{                                                                                                                            \\r
+                ret = call;                                                                                                                    \\r
+               throw_on_ffmpeg_error(ret, source, THROW_ON_ERROR_STR(call), __FUNCTION__, __FILE__, __LINE__); \\r
+               return ret;                                                                                                                     \\r
+               }catch(...){CASPAR_LOG_CURRENT_EXCEPTION();}                                            \\r
+               return ret;                                                                                                                     \\r
+       }()\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/audio/audio_decoder.cpp b/modules/ffmpeg/producer/audio/audio_decoder.cpp
new file mode 100644 (file)
index 0000000..b032c0f
--- /dev/null
@@ -0,0 +1,158 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "audio_decoder.h"\r
+\r
+#include "audio_resampler.h"\r
+\r
+#include "../util/util.h"\r
+#include "../../ffmpeg_error.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+#include <queue>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libavformat/avformat.h>\r
+       #include <libavcodec/avcodec.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+struct audio_decoder::implementation : boost::noncopyable\r
+{      \r
+       int                                                                                                                     index_;\r
+       const safe_ptr<AVCodecContext>                                                          codec_context_;         \r
+       const core::video_format_desc                                                           format_desc_;\r
+\r
+       audio_resampler                                                                                         resampler_;\r
+\r
+       std::vector<int8_t,  tbb::cache_aligned_allocator<int8_t>>      buffer1_;\r
+\r
+       std::queue<safe_ptr<AVPacket>>                                                          packets_;\r
+\r
+       const int64_t                                                                                           nb_frames_;\r
+       tbb::atomic<size_t>                                                                                     file_frame_number_;\r
+public:\r
+       explicit implementation(const safe_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) \r
+               : format_desc_(format_desc)     \r
+               , codec_context_(open_codec(*context, AVMEDIA_TYPE_AUDIO, index_))\r
+               , resampler_(format_desc.audio_channels,        codec_context_->channels,\r
+                                        format_desc.audio_sample_rate, codec_context_->sample_rate,\r
+                                        AV_SAMPLE_FMT_S32,                             codec_context_->sample_fmt)\r
+               , buffer1_(AVCODEC_MAX_AUDIO_FRAME_SIZE*2)\r
+               , nb_frames_(0)//context->streams[index_]->nb_frames)\r
+       {               \r
+               file_frame_number_ = 0;   \r
+       }\r
+\r
+       void push(const std::shared_ptr<AVPacket>& packet)\r
+       {                       \r
+               if(!packet)\r
+                       return;\r
+\r
+               if(packet->stream_index == index_ || packet->data == nullptr)\r
+                       packets_.push(make_safe_ptr(packet));\r
+       }       \r
+       \r
+       std::shared_ptr<core::audio_buffer> poll()\r
+       {\r
+               if(packets_.empty())\r
+                       return nullptr;\r
+                               \r
+               auto packet = packets_.front();\r
+\r
+               if(packet->data == nullptr)\r
+               {\r
+                       packets_.pop();\r
+                       file_frame_number_ = static_cast<size_t>(packet->pos);\r
+                       avcodec_flush_buffers(codec_context_.get());\r
+                       return flush_audio();\r
+               }\r
+\r
+               auto audio = decode(*packet);\r
+\r
+               if(packet->size == 0)                                   \r
+                       packets_.pop();\r
+\r
+               return audio;\r
+       }\r
+\r
+       std::shared_ptr<core::audio_buffer> decode(AVPacket& pkt)\r
+       {               \r
+               buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);\r
+               int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
+               \r
+               int ret = THROW_ON_ERROR2(avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, &pkt), "[audio_decoder]");\r
+\r
+               // There might be several frames in one packet.\r
+               pkt.size -= ret;\r
+               pkt.data += ret;\r
+                       \r
+               buffer1_.resize(written_bytes);\r
+\r
+               buffer1_ = resampler_.resample(std::move(buffer1_));\r
+               \r
+               const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32);\r
+               const auto samples = reinterpret_cast<int32_t*>(buffer1_.data());\r
+\r
+               ++file_frame_number_;\r
+\r
+               return std::make_shared<core::audio_buffer>(samples, samples + n_samples);\r
+       }\r
+\r
+       bool ready() const\r
+       {\r
+               return packets_.size() > 10;\r
+       }\r
+\r
+       uint32_t nb_frames() const\r
+       {\r
+               return 0;//std::max<int64_t>(nb_frames_, file_frame_number_);\r
+       }\r
+\r
+       std::wstring print() const\r
+       {               \r
+               return L"[audio-decoder] " + widen(codec_context_->codec->long_name);\r
+       }\r
+};\r
+\r
+audio_decoder::audio_decoder(const safe_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) : impl_(new implementation(context, format_desc)){}\r
+void audio_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
+bool audio_decoder::ready() const{return impl_->ready();}\r
+std::shared_ptr<core::audio_buffer> audio_decoder::poll(){return impl_->poll();}\r
+uint32_t audio_decoder::nb_frames() const{return impl_->nb_frames();}\r
+uint32_t audio_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
+std::wstring audio_decoder::print() const{return impl_->print();}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/audio/audio_decoder.h b/modules/ffmpeg/producer/audio/audio_decoder.h
new file mode 100644 (file)
index 0000000..bb5c120
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/mixer/audio/audio_mixer.h>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+struct AVPacket;\r
+struct AVFormatContext;\r
+\r
+namespace caspar { \r
+                       \r
+namespace core {\r
+\r
+struct video_format_desc;\r
+\r
+}\r
+\r
+namespace ffmpeg {\r
+       \r
+class audio_decoder : boost::noncopyable\r
+{\r
+public:\r
+       explicit audio_decoder(const safe_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc);\r
+       \r
+       bool ready() const;\r
+       void push(const std::shared_ptr<AVPacket>& packet);\r
+       std::shared_ptr<core::audio_buffer> poll();\r
+\r
+       uint32_t nb_frames() const;\r
+       \r
+       uint32_t file_frame_number() const;\r
+\r
+       std::wstring print() const;\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/audio/audio_resampler.cpp b/modules/ffmpeg/producer/audio/audio_resampler.cpp
new file mode 100644 (file)
index 0000000..7d6afb7
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../StdAfx.h"\r
+\r
+#include "audio_resampler.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libavcodec/avcodec.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+struct audio_resampler::implementation\r
+{      \r
+       std::shared_ptr<ReSampleContext> resampler_;\r
+       \r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> copy_buffer_;\r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer2_;\r
+\r
+       const size_t                    output_channels_;\r
+       const AVSampleFormat    output_sample_format_;\r
+\r
+       const size_t                    input_channels_;\r
+       const AVSampleFormat    input_sample_format_;\r
+\r
+       implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
+               : output_channels_(output_channels)\r
+               , output_sample_format_(output_sample_format)\r
+               , input_channels_(input_channels)\r
+               , input_sample_format_(input_sample_format)\r
+       {\r
+               if(input_channels               != output_channels || \r
+                  input_sample_rate    != output_sample_rate ||\r
+                  input_sample_format  != output_sample_format)\r
+               {       \r
+                       auto resampler = av_audio_resample_init(output_channels,                input_channels,\r
+                                                                                                       output_sample_rate,             input_sample_rate,\r
+                                                                                                       output_sample_format,   input_sample_format,\r
+                                                                                                       16, 10, 0, 0.8);\r
+\r
+                       buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);\r
+\r
+                       char sample_fmt_string[200];\r
+                       av_get_sample_fmt_string(sample_fmt_string, 200, input_sample_format);\r
+\r
+                       CASPAR_LOG(warning) << L"[audio-resampler]"             \r
+                                                               << L" sample-rate: "    << input_sample_rate \r
+                                                               << L" channels: "               << input_channels \r
+                                                               << L" sample-fmt: "             << widen(sample_fmt_string);\r
+\r
+                       if(resampler)\r
+                               resampler_.reset(resampler, audio_resample_close);\r
+                       else\r
+                               BOOST_THROW_EXCEPTION(caspar_exception());\r
+               }               \r
+       }\r
+\r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data)\r
+       {\r
+               if(resampler_ && !data.empty())\r
+               {\r
+                       buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);\r
+                       auto ret = audio_resample(resampler_.get(),\r
+                                                                         reinterpret_cast<short*>(buffer2_.data()), \r
+                                                                         reinterpret_cast<short*>(data.data()), \r
+                                                                         data.size() / (av_get_bytes_per_sample(input_sample_format_) * input_channels_)); \r
+                       buffer2_.resize(ret * av_get_bytes_per_sample(output_sample_format_) * output_channels_);\r
+                       std::swap(data, buffer2_);\r
+               }\r
+\r
+               return std::move(data);\r
+       }\r
+};\r
+\r
+\r
+audio_resampler::audio_resampler(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
+                               : impl_(new implementation(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format)){}\r
+std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> audio_resampler::resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data){return impl_->resample(std::move(data));}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/audio/audio_resampler.h b/modules/ffmpeg/producer/audio/audio_resampler.h
new file mode 100644 (file)
index 0000000..cb50ebd
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <memory>\r
+\r
+#include <libavutil/samplefmt.h>\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+class audio_resampler\r
+{\r
+public:\r
+       audio_resampler(size_t                  output_channels,                size_t                  input_channels, \r
+                                       size_t                  output_sample_rate,             size_t                  input_sample_rate, \r
+                                       AVSampleFormat  output_sample_format,   AVSampleFormat  input_sample_format);\r
+       \r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data);\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/ffmpeg_producer.cpp b/modules/ffmpeg/producer/ffmpeg_producer.cpp
new file mode 100644 (file)
index 0000000..e5b0343
--- /dev/null
@@ -0,0 +1,462 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "ffmpeg_producer.h"\r
+\r
+#include "../ffmpeg_error.h"\r
+#include "../ffmpeg.h"\r
+\r
+#include "muxer/frame_muxer.h"\r
+#include "input/input.h"\r
+#include "util/util.h"\r
+#include "audio/audio_decoder.h"\r
+#include "video/video_decoder.h"\r
+\r
+#include <common/env.h>\r
+#include <common/utility/assert.h>\r
+#include <common/utility/param.h>\r
+#include <common/diagnostics/graph.h>\r
+\r
+#include <core/video_format.h>\r
+#include <core/producer/frame_producer.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/assign.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/range/algorithm/find_if.hpp>\r
+#include <boost/range/algorithm/find.hpp>\r
+#include <boost/regex.hpp>\r
+\r
+#include <tbb/parallel_invoke.h>\r
+\r
+#include <limits>\r
+#include <memory>\r
+#include <queue>\r
+\r
+namespace caspar { namespace ffmpeg {\r
+                               \r
+struct ffmpeg_producer : public core::frame_producer\r
+{\r
+       const std::wstring                                                                                      filename_;\r
+       \r
+       const safe_ptr<diagnostics::graph>                                                      graph_;\r
+       boost::timer                                                                                            frame_timer_;\r
+                                       \r
+       const safe_ptr<core::frame_factory>                                                     frame_factory_;\r
+       const core::video_format_desc                                                           format_desc_;\r
+\r
+       std::shared_ptr<void>                                                                           initial_logger_disabler_;\r
+\r
+       input                                                                                                           input_; \r
+       std::unique_ptr<video_decoder>                                                          video_decoder_;\r
+       std::unique_ptr<audio_decoder>                                                          audio_decoder_; \r
+       std::unique_ptr<frame_muxer>                                                            muxer_;\r
+\r
+       const double                                                                                            fps_;\r
+       const uint32_t                                                                                          start_;\r
+       const uint32_t                                                                                          length_;\r
+       const bool                                                                                                      thumbnail_mode_;\r
+\r
+       safe_ptr<core::basic_frame>                                                                     last_frame_;\r
+       \r
+       std::queue<std::pair<safe_ptr<core::basic_frame>, size_t>>      frame_buffer_;\r
+\r
+       int64_t                                                                                                         frame_number_;\r
+       uint32_t                                                                                                        file_frame_number_;\r
+       \r
+public:\r
+       explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode)\r
+               : filename_(filename)\r
+               , frame_factory_(frame_factory)         \r
+               , format_desc_(frame_factory->get_video_format_desc())\r
+               , initial_logger_disabler_(temporary_disable_logging_for_thread(thumbnail_mode))\r
+               , input_(graph_, filename_, loop, start, length, thumbnail_mode)\r
+               , fps_(read_fps(*input_.context(), format_desc_.fps))\r
+               , start_(start)\r
+               , length_(length)\r
+               , thumbnail_mode_(thumbnail_mode)\r
+               , last_frame_(core::basic_frame::empty())\r
+               , frame_number_(0)\r
+       {\r
+               graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
+               graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f));   \r
+               diagnostics::register_graph(graph_);\r
+       \r
+               try\r
+               {\r
+                       video_decoder_.reset(new video_decoder(input_.context()));\r
+                       if (!thumbnail_mode_)\r
+                               CASPAR_LOG(info) << print() << L" " << video_decoder_->print();\r
+               }\r
+               catch(averror_stream_not_found&)\r
+               {\r
+                       //CASPAR_LOG(warning) << print() << " No video-stream found. Running without video.";   \r
+               }\r
+               catch(...)\r
+               {\r
+                       if (!thumbnail_mode_)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(warning) << print() << "Failed to open video-stream. Running without video.";        \r
+                       }\r
+               }\r
+\r
+               if (!thumbnail_mode_)\r
+               {\r
+                       try\r
+                       {\r
+                               audio_decoder_.reset(new audio_decoder(input_.context(), frame_factory->get_video_format_desc()));\r
+                               CASPAR_LOG(info) << print() << L" " << audio_decoder_->print();\r
+                       }\r
+                       catch(averror_stream_not_found&)\r
+                       {\r
+                               //CASPAR_LOG(warning) << print() << " No audio-stream found. Running without audio.";   \r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(warning) << print() << " Failed to open audio-stream. Running without audio.";               \r
+                       }\r
+               }\r
+\r
+               if(!video_decoder_ && !audio_decoder_)\r
+                       BOOST_THROW_EXCEPTION(averror_stream_not_found() << msg_info("No streams found"));\r
+\r
+               muxer_.reset(new frame_muxer(fps_, frame_factory, thumbnail_mode_, filter));\r
+       }\r
+\r
+       // frame_producer\r
+       \r
+       virtual safe_ptr<core::basic_frame> receive(int hints) override\r
+       {\r
+               return render_frame(hints).first;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return disable_audio(last_frame_);\r
+       }\r
+\r
+       std::pair<safe_ptr<core::basic_frame>, uint32_t> render_frame(int hints)\r
+       {               \r
+               frame_timer_.restart();\r
+               auto disable_logging = temporary_disable_logging_for_thread(thumbnail_mode_);\r
+                               \r
+               for(int n = 0; n < 16 && frame_buffer_.size() < 2; ++n)\r
+                       try_decode_frame(hints);\r
+               \r
+               graph_->set_value("frame-time", frame_timer_.elapsed()*format_desc_.fps*0.5);\r
+                               \r
+               if(frame_buffer_.empty() && input_.eof())\r
+                       return std::make_pair(last_frame(), -1);\r
+\r
+               if(frame_buffer_.empty())\r
+               {\r
+                       graph_->set_tag("underflow");   \r
+                       return std::make_pair(core::basic_frame::late(), -1);\r
+               }\r
+               \r
+               auto frame = frame_buffer_.front(); \r
+               frame_buffer_.pop();\r
+               \r
+               ++frame_number_;\r
+               file_frame_number_ = frame.second;\r
+\r
+               graph_->set_text(print());\r
+\r
+               last_frame_ = frame.first;\r
+\r
+               return frame;\r
+       }\r
+\r
+       safe_ptr<core::basic_frame> render_specific_frame(uint32_t file_position, int hints)\r
+       {\r
+               // Some trial and error and undeterministic stuff here\r
+               static const int NUM_RETRIES = 32;\r
+               \r
+               if (file_position > 0) // Assume frames are requested in sequential order,\r
+                                          // therefore no seeking should be necessary for the first frame.\r
+               {\r
+                       input_.seek(file_position > 1 ? file_position - 2: file_position).get();\r
+                       boost::this_thread::sleep(boost::posix_time::milliseconds(40));\r
+               }\r
+\r
+               for (int i = 0; i < NUM_RETRIES; ++i)\r
+               {\r
+                       boost::this_thread::sleep(boost::posix_time::milliseconds(40));\r
+               \r
+                       auto frame = render_frame(hints);\r
+\r
+                       if (frame.second == std::numeric_limits<uint32_t>::max())\r
+                       {\r
+                               // Retry\r
+                               continue;\r
+                       }\r
+                       else if (frame.second == file_position + 1 || frame.second == file_position)\r
+                               return frame.first;\r
+                       else if (frame.second > file_position + 1)\r
+                       {\r
+                               CASPAR_LOG(trace) << print() << L" " << frame.second << L" received, wanted " << file_position + 1;\r
+                               int64_t adjusted_seek = file_position - (frame.second - file_position + 1);\r
+\r
+                               if (adjusted_seek > 1 && file_position > 0)\r
+                               {\r
+                                       CASPAR_LOG(trace) << print() << L" adjusting to " << adjusted_seek;\r
+                                       input_.seek(static_cast<uint32_t>(adjusted_seek) - 1).get();\r
+                                       boost::this_thread::sleep(boost::posix_time::milliseconds(40));\r
+                               }\r
+                               else\r
+                                       return frame.first;\r
+                       }\r
+               }\r
+\r
+               CASPAR_LOG(trace) << print() << " Giving up finding frame at " << file_position;\r
+               return core::basic_frame::empty();\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
+       {\r
+               auto disable_logging = temporary_disable_logging_for_thread(thumbnail_mode_);\r
+               auto total_frames = nb_frames();\r
+               auto grid = env::properties().get(L"configuration.thumbnails.video-grid", 2);\r
+\r
+               if (grid < 1)\r
+               {\r
+                       CASPAR_LOG(error) << L"configuration/thumbnails/video-grid cannot be less than 1";\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("configuration/thumbnails/video-grid cannot be less than 1"));\r
+               }\r
+\r
+               if (grid == 1)\r
+               {\r
+                       return render_specific_frame(total_frames / 2, 0/*DEINTERLACE_HINT*/);\r
+               }\r
+\r
+               auto num_snapshots = grid * grid;\r
+\r
+               std::vector<safe_ptr<core::basic_frame>> frames;\r
+\r
+               for (int i = 0; i < num_snapshots; ++i)\r
+               {\r
+                       int x = i % grid;\r
+                       int y = i / grid;\r
+                       int desired_frame;\r
+                       \r
+                       if (i == 0)\r
+                               desired_frame = 0; // first\r
+                       else if (i == num_snapshots - 1)\r
+                               desired_frame = total_frames - 1; // last\r
+                       else\r
+                               // evenly distributed across the file.\r
+                               desired_frame = total_frames * i / (num_snapshots - 1);\r
+\r
+                       auto frame = render_specific_frame(desired_frame, 0/*DEINTERLACE_HINT*/);\r
+                       frame->get_frame_transform().fill_scale[0] = 1.0 / static_cast<double>(grid);\r
+                       frame->get_frame_transform().fill_scale[1] = 1.0 / static_cast<double>(grid);\r
+                       frame->get_frame_transform().fill_translation[0] = 1.0 / static_cast<double>(grid) * x;\r
+                       frame->get_frame_transform().fill_translation[1] = 1.0 / static_cast<double>(grid) * y;\r
+\r
+                       frames.push_back(frame);\r
+               }\r
+\r
+               return make_safe<core::basic_frame>(frames);\r
+       }\r
+\r
+       virtual uint32_t nb_frames() const override\r
+       {\r
+               if(input_.loop())\r
+                       return std::numeric_limits<uint32_t>::max();\r
+\r
+               uint32_t nb_frames = file_nb_frames();\r
+\r
+               nb_frames = std::min(length_, nb_frames);\r
+               nb_frames = muxer_->calc_nb_frames(nb_frames);\r
+               \r
+               return nb_frames > start_ ? nb_frames - start_ : 0;\r
+       }\r
+\r
+       uint32_t file_nb_frames() const\r
+       {\r
+               uint32_t file_nb_frames = 0;\r
+               file_nb_frames = std::max(file_nb_frames, video_decoder_ ? video_decoder_->nb_frames() : 0);\r
+               file_nb_frames = std::max(file_nb_frames, audio_decoder_ ? audio_decoder_->nb_frames() : 0);\r
+               return file_nb_frames;\r
+       }\r
+       \r
+       virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
+       {\r
+               boost::promise<std::wstring> promise;\r
+               promise.set_value(do_call(param));\r
+               return promise.get_future();\r
+       }\r
+                               \r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"|" \r
+                                                 + print_mode() + L"|" \r
+                                                 + boost::lexical_cast<std::wstring>(file_frame_number_) + L"/" + boost::lexical_cast<std::wstring>(file_nb_frames()) + L"]";\r
+       }\r
+\r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type",                               L"ffmpeg-producer");\r
+               info.add(L"filename",                   filename_);\r
+               info.add(L"width",                              video_decoder_ ? video_decoder_->width() : 0);\r
+               info.add(L"height",                             video_decoder_ ? video_decoder_->height() : 0);\r
+               info.add(L"progressive",                video_decoder_ ? video_decoder_->is_progressive() : false);\r
+               info.add(L"fps",                                fps_);\r
+               info.add(L"loop",                               input_.loop());\r
+               info.add(L"frame-number",               frame_number_);\r
+               auto nb_frames2 = nb_frames();\r
+               info.add(L"nb-frames",                  nb_frames2 == std::numeric_limits<int64_t>::max() ? -1 : nb_frames2);\r
+               info.add(L"file-frame-number",  file_frame_number_);\r
+               info.add(L"file-nb-frames",             file_nb_frames());\r
+               return info;\r
+       }\r
+\r
+       // ffmpeg_producer\r
+\r
+       std::wstring print_mode() const\r
+       {\r
+               return video_decoder_ ? ffmpeg::print_mode(video_decoder_->width(), video_decoder_->height(), fps_, !video_decoder_->is_progressive()) : L"";\r
+       }\r
+                                       \r
+       std::wstring do_call(const std::wstring& param)\r
+       {\r
+               static const boost::wregex loop_exp(L"LOOP\\s*(?<VALUE>\\d?)?", boost::regex::icase);\r
+               static const boost::wregex seek_exp(L"SEEK\\s+(?<VALUE>\\d+)", boost::regex::icase);\r
+               \r
+               boost::wsmatch what;\r
+               if(boost::regex_match(param, what, loop_exp))\r
+               {\r
+                       if(!what["VALUE"].str().empty())\r
+                               input_.loop(boost::lexical_cast<bool>(what["VALUE"].str()));\r
+                       return boost::lexical_cast<std::wstring>(input_.loop());\r
+               }\r
+               if(boost::regex_match(param, what, seek_exp))\r
+               {\r
+                       input_.seek(boost::lexical_cast<uint32_t>(what["VALUE"].str()));\r
+                       return L"";\r
+               }\r
+\r
+               BOOST_THROW_EXCEPTION(invalid_argument());\r
+       }\r
+\r
+       void try_decode_frame(int hints)\r
+       {\r
+               std::shared_ptr<AVPacket> pkt;\r
+\r
+               for(int n = 0; n < 32 && ((video_decoder_ && !video_decoder_->ready()) || (audio_decoder_ && !audio_decoder_->ready())) && input_.try_pop(pkt); ++n)\r
+               {\r
+                       if(video_decoder_)\r
+                               video_decoder_->push(pkt);\r
+                       if(audio_decoder_)\r
+                               audio_decoder_->push(pkt);\r
+               }\r
+               \r
+               std::shared_ptr<AVFrame>                        video;\r
+               std::shared_ptr<core::audio_buffer> audio;\r
+\r
+               tbb::parallel_invoke(\r
+               [&]\r
+               {\r
+                       if(!muxer_->video_ready() && video_decoder_)    \r
+                               video = video_decoder_->poll(); \r
+               },\r
+               [&]\r
+               {               \r
+                       if(!muxer_->audio_ready() && audio_decoder_)            \r
+                               audio = audio_decoder_->poll();         \r
+               });\r
+               \r
+               muxer_->push(video, hints);\r
+               muxer_->push(audio);\r
+\r
+               if(!audio_decoder_)\r
+               {\r
+                       if(video == flush_video())\r
+                               muxer_->push(flush_audio());\r
+                       else if(!muxer_->audio_ready())\r
+                               muxer_->push(empty_audio());\r
+               }\r
+\r
+               if(!video_decoder_)\r
+               {\r
+                       if(audio == flush_audio())\r
+                               muxer_->push(flush_video(), 0);\r
+                       else if(!muxer_->video_ready())\r
+                               muxer_->push(empty_video(), 0);\r
+               }\r
+               \r
+               size_t file_frame_number = 0;\r
+               file_frame_number = std::max(file_frame_number, video_decoder_ ? video_decoder_->file_frame_number() : 0);\r
+               //file_frame_number = std::max(file_frame_number, audio_decoder_ ? audio_decoder_->file_frame_number() : 0);\r
+\r
+               for(auto frame = muxer_->poll(); frame; frame = muxer_->poll())\r
+                       frame_buffer_.push(std::make_pair(make_safe_ptr(frame), file_frame_number));\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{              \r
+       static const std::vector<std::wstring> invalid_exts = boost::assign::list_of(L".png")(L".tga")(L".bmp")(L".jpg")(L".jpeg")(L".gif")(L".tiff")(L".tif")(L".jp2")(L".jpx")(L".j2k")(L".j2c")(L".swf")(L".ct");\r
+       auto filename = probe_stem(env::media_folder() + L"\\" + params.at(0), invalid_exts);\r
+\r
+       if(filename.empty())\r
+               return core::frame_producer::empty();\r
+       \r
+       auto loop               = boost::range::find(params, L"LOOP") != params.end();\r
+       auto start              = get_param(L"SEEK", params, static_cast<uint32_t>(0));\r
+       auto length             = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max());\r
+       auto filter_str = get_param(L"FILTER", params, L"");    \r
+               \r
+       boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
+       boost::replace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1");\r
+       \r
+       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length, false));\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{              \r
+       static const std::vector<std::wstring> invalid_exts = boost::assign::list_of\r
+                       (L".png")(L".tga")(L".bmp")(L".jpg")(L".jpeg")(L".gif")(L".tiff")(L".tif")(L".jp2")(L".jpx")(L".j2k")(L".j2c")(L".swf")(L".ct")\r
+                       (L".wav")(L".mp3"); // audio shall not have thumbnails\r
+       auto filename = probe_stem(env::media_folder() + L"\\" + params.at(0), invalid_exts);\r
+\r
+       if(filename.empty())\r
+               return core::frame_producer::empty();\r
+       \r
+       auto loop               = false;\r
+       auto start              = 0;\r
+       auto length             = std::numeric_limits<uint32_t>::max();\r
+       auto filter_str = L"";\r
+               \r
+       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length, true));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/ffmpeg_producer.h b/modules/ffmpeg/producer/ffmpeg_producer.h
new file mode 100644 (file)
index 0000000..66aaf71
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar {\r
+\r
+namespace core {\r
+\r
+struct frame_producer;\r
+struct frame_factory;\r
+\r
+}\r
+       \r
+namespace ffmpeg {\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/filter/filter.cpp b/modules/ffmpeg/producer/filter/filter.cpp
new file mode 100644 (file)
index 0000000..9c2ef15
--- /dev/null
@@ -0,0 +1,331 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "filter.h"\r
+\r
+#include "parallel_yadif.h"\r
+\r
+#include "../../ffmpeg_error.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
+#include <boost/range/adaptors.hpp>\r
+#include <boost/assign.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/foreach.hpp>\r
+\r
+#include <cstdio>\r
+#include <sstream>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libavutil/avutil.h>\r
+       #include <libavutil/imgutils.h>\r
+       #include <libavfilter/avfilter.h>\r
+       #include <libavfilter/avcodec.h>\r
+       #include <libavfilter/avfiltergraph.h>\r
+       #include <libavfilter/buffersink.h>\r
+       #include <libavfilter/vsrc_buffer.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+static int query_formats_444(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUV444P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+static int query_formats_422(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUV422P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+static int query_formats_420(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUV420P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+static int query_formats_420a(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUVA420P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+static int query_formats_411(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUV411P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+static int query_formats_410(AVFilterContext *ctx)\r
+{\r
+    static const int pix_fmts[] = {PIX_FMT_YUV410P, PIX_FMT_NONE};\r
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));\r
+    return 0;\r
+}\r
+\r
+struct filter::implementation\r
+{\r
+       std::wstring                                    filters_;\r
+       std::shared_ptr<AVFilterGraph>  graph_; \r
+       AVFilterContext*                                buffersink_ctx_;\r
+       AVFilterContext*                                buffersrc_ctx_;\r
+       std::shared_ptr<void>                   parallel_yadif_ctx_;\r
+       std::vector<PixelFormat>                pix_fmts_;\r
+       std::queue<safe_ptr<AVFrame>>   bypass_;\r
+               \r
+       implementation(const std::wstring& filters, const std::vector<PixelFormat>& pix_fmts) \r
+               : filters_(filters)\r
+               , parallel_yadif_ctx_(nullptr)\r
+               , pix_fmts_(pix_fmts)\r
+       {\r
+               if(pix_fmts_.empty())\r
+               {\r
+                       pix_fmts_ = boost::assign::list_of\r
+                               (PIX_FMT_YUVA420P)\r
+                               (PIX_FMT_YUV444P)\r
+                               (PIX_FMT_YUV422P)\r
+                               (PIX_FMT_YUV420P)\r
+                               (PIX_FMT_YUV411P)\r
+                               (PIX_FMT_BGRA)\r
+                               (PIX_FMT_ARGB)\r
+                               (PIX_FMT_RGBA)\r
+                               (PIX_FMT_ABGR)\r
+                               (PIX_FMT_GRAY8);\r
+               }\r
+               \r
+               pix_fmts_.push_back(PIX_FMT_NONE);\r
+       }\r
+       \r
+       void push(const std::shared_ptr<AVFrame>& frame)\r
+       {               \r
+               if(!frame)\r
+                       return;\r
+\r
+               if(frame->data[0] == nullptr || frame->width < 1)\r
+                       BOOST_THROW_EXCEPTION(invalid_argument());\r
+\r
+               if(filters_.empty())\r
+               {\r
+                       bypass_.push(make_safe_ptr(frame));\r
+                       return;\r
+               }\r
+               \r
+               try\r
+               {\r
+                       if(!graph_)\r
+                       {\r
+                               try\r
+                               {\r
+                                       graph_.reset(avfilter_graph_alloc(), [](AVFilterGraph* p){avfilter_graph_free(&p);});\r
+                                                               \r
+                                       // Input\r
+                                       std::stringstream args;\r
+                                       args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio\r
+                                       THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]");\r
+                                       \r
+#if FF_API_OLD_VSINK_API\r
+                                       THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts_.data(), graph_.get()), "[filter]");\r
+#else\r
+                                       safe_ptr<AVBufferSinkParams> buffersink_params(av_buffersink_params_alloc(), av_free);\r
+                                       buffersink_params->pixel_fmts = pix_fmts_.data();\r
+                                       THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, buffersink_params.get(), graph_.get()), "[filter]");\r
+#endif\r
+                                       AVFilterInOut* inputs  = avfilter_inout_alloc();\r
+                                       AVFilterInOut* outputs = avfilter_inout_alloc();\r
+                                                               \r
+                                       outputs->name                   = av_strdup("in");\r
+                                       outputs->filter_ctx             = buffersrc_ctx_;\r
+                                       outputs->pad_idx                = 0;\r
+                                       outputs->next                   = nullptr;\r
+\r
+                                       inputs->name                    = av_strdup("out");\r
+                                       inputs->filter_ctx              = buffersink_ctx_;\r
+                                       inputs->pad_idx                 = 0;\r
+                                       inputs->next                    = nullptr;\r
+                       \r
+                                       std::string filters = boost::to_lower_copy(narrow(filters_));\r
+                                       THROW_ON_ERROR2(avfilter_graph_parse(graph_.get(), filters.c_str(), &inputs, &outputs, NULL), "[filter]");\r
+                       \r
+                                       auto yadif_filter = boost::adaptors::filtered([&](AVFilterContext* p){return strstr(p->name, "yadif") != 0;});\r
+\r
+                                       BOOST_FOREACH(auto filter_ctx, boost::make_iterator_range(graph_->filters, graph_->filters + graph_->filter_count) | yadif_filter)\r
+                                       {\r
+                                               // Don't trust that libavfilter chooses optimal format.\r
+                                               filter_ctx->filter->query_formats = [&]() -> int (*)(AVFilterContext*)\r
+                                               {\r
+                                                       switch(frame->format)\r
+                                                       {\r
+                                                       case PIX_FMT_YUV444P16: \r
+                                                       case PIX_FMT_YUV444P10: \r
+                                                       case PIX_FMT_YUV444P9:          \r
+                                                       case PIX_FMT_YUV444P:   \r
+                                                       case PIX_FMT_BGR24:             \r
+                                                       case PIX_FMT_RGB24:     \r
+                                                               return query_formats_444;\r
+                                                       case PIX_FMT_YUV422P16: \r
+                                                       case PIX_FMT_YUV422P10: \r
+                                                       case PIX_FMT_YUV422P9:  \r
+                                                       case PIX_FMT_YUV422P:   \r
+                                                       case PIX_FMT_UYVY422:   \r
+                                                       case PIX_FMT_YUYV422:   \r
+                                                               return query_formats_422;\r
+                                                       case PIX_FMT_YUV420P16: \r
+                                                       case PIX_FMT_YUV420P10: \r
+                                                       case PIX_FMT_YUV420P9:  \r
+                                                       case PIX_FMT_YUV420P:   \r
+                                                               return query_formats_420;\r
+                                                       case PIX_FMT_YUVA420P:  \r
+                                                       case PIX_FMT_BGRA:              \r
+                                                       case PIX_FMT_RGBA:              \r
+                                                       case PIX_FMT_ABGR:              \r
+                                                       case PIX_FMT_ARGB:              \r
+                                                               return query_formats_420a;\r
+                                                       case PIX_FMT_UYYVYY411: \r
+                                                       case PIX_FMT_YUV411P:   \r
+                                                               return query_formats_411;\r
+                                                       case PIX_FMT_YUV410P:   \r
+                                                               return query_formats_410;\r
+                                                       default:                                \r
+                                                               return filter_ctx->filter->query_formats;\r
+                                                       }\r
+                                               }();\r
+                                       }\r
+                                       \r
+                                       THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]"); \r
+                                       \r
+                                       BOOST_FOREACH(auto filter_ctx, boost::make_iterator_range(graph_->filters, graph_->filters + graph_->filter_count) | yadif_filter)                                              \r
+                                               parallel_yadif_ctx_ = make_parallel_yadif(filter_ctx);                                          \r
+                               }\r
+                               catch(...)\r
+                               {\r
+                                       graph_ = nullptr;\r
+                                       throw;\r
+                               }\r
+                       }\r
+               \r
+                       THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]");\r
+               }\r
+               catch(ffmpeg_error&)\r
+               {\r
+                       throw;\r
+               }\r
+               catch(...)\r
+               {\r
+                       BOOST_THROW_EXCEPTION(ffmpeg_error() << boost::errinfo_nested_exception(boost::current_exception()));\r
+               }\r
+       }\r
+\r
+       std::shared_ptr<AVFrame> poll()\r
+       {\r
+               if(filters_.empty())\r
+               {\r
+                       if(bypass_.empty())\r
+                               return nullptr;\r
+                       auto frame = bypass_.front();\r
+                       bypass_.pop();\r
+                       return frame;\r
+               }\r
+\r
+               if(!graph_)\r
+                       return nullptr;\r
+               \r
+               try\r
+               {\r
+                       if(avfilter_poll_frame(buffersink_ctx_->inputs[0])) \r
+                       {\r
+                               AVFilterBufferRef *picref;\r
+                               THROW_ON_ERROR2(av_buffersink_get_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]");\r
+\r
+                               if (!picref) \r
+                                       return nullptr;\r
+                               \r
+                               safe_ptr<AVFrame> frame(avcodec_alloc_frame(), [=](AVFrame* p)\r
+                               {\r
+                                       av_free(p);\r
+                                       avfilter_unref_buffer(picref);\r
+                               });\r
+\r
+                               avcodec_get_frame_defaults(frame.get());        \r
+\r
+                               memcpy(frame->data,     picref->data,     sizeof(frame->data));\r
+                               memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize));\r
+                               frame->format                           = picref->format;\r
+                               frame->width                            = picref->video->w;\r
+                               frame->height                           = picref->video->h;\r
+                               frame->pkt_pos                          = picref->pos;\r
+                               frame->interlaced_frame         = picref->video->interlaced;\r
+                               frame->top_field_first          = picref->video->top_field_first;\r
+                               frame->key_frame                        = picref->video->key_frame;\r
+                               frame->pict_type                        = picref->video->pict_type;\r
+                               frame->sample_aspect_ratio      = picref->video->sample_aspect_ratio;\r
+                                       \r
+                               return frame;                           \r
+                       }\r
+\r
+                       return nullptr;\r
+               }\r
+               catch(ffmpeg_error&)\r
+               {\r
+                       throw;\r
+               }\r
+               catch(...)\r
+               {\r
+                       BOOST_THROW_EXCEPTION(ffmpeg_error() << boost::errinfo_nested_exception(boost::current_exception()));\r
+               }\r
+       }\r
+};\r
+\r
+filter::filter(const std::wstring& filters, const std::vector<PixelFormat>& pix_fmts) : impl_(new implementation(filters, pix_fmts)){}\r
+filter::filter(filter&& other) : impl_(std::move(other.impl_)){}\r
+filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;}\r
+void filter::push(const std::shared_ptr<AVFrame>& frame){impl_->push(frame);}\r
+std::shared_ptr<AVFrame> filter::poll(){return impl_->poll();}\r
+std::wstring filter::filter_str() const{return impl_->filters_;}\r
+std::vector<safe_ptr<AVFrame>> filter::poll_all()\r
+{      \r
+       std::vector<safe_ptr<AVFrame>> frames;\r
+       for(auto frame = poll(); frame; frame = poll())\r
+               frames.push_back(make_safe_ptr(frame));\r
+       return frames;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/filter/filter.h b/modules/ffmpeg/producer/filter/filter.h
new file mode 100644 (file)
index 0000000..f198920
--- /dev/null
@@ -0,0 +1,97 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/algorithm/string/case_conv.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+struct AVFrame;\r
+enum PixelFormat;\r
+\r
+namespace caspar { namespace ffmpeg {\r
+\r
+static std::wstring append_filter(const std::wstring& filters, const std::wstring& filter)\r
+{\r
+       return filters + (filters.empty() ? L"" : L",") + filter;\r
+}\r
+\r
+class filter : boost::noncopyable\r
+{\r
+public:\r
+       filter(const std::wstring& filters = L"", const std::vector<PixelFormat>& pix_fmts = std::vector<PixelFormat>());\r
+       filter(filter&& other);\r
+       filter& operator=(filter&& other);\r
+\r
+       void push(const std::shared_ptr<AVFrame>& frame);\r
+       std::shared_ptr<AVFrame> poll();\r
+       std::vector<safe_ptr<AVFrame>> poll_all();\r
+\r
+       std::wstring filter_str() const;\r
+                       \r
+       static bool is_double_rate(const std::wstring& filters)\r
+       {\r
+               if(boost::to_upper_copy(filters).find(L"YADIF=1") != std::string::npos)\r
+                       return true;\r
+       \r
+               if(boost::to_upper_copy(filters).find(L"YADIF=3") != std::string::npos)\r
+                       return true;\r
+\r
+               return false;\r
+       }\r
+\r
+       static bool is_deinterlacing(const std::wstring& filters)\r
+       {\r
+               if(boost::to_upper_copy(filters).find(L"YADIF") != std::string::npos)\r
+                       return true;    \r
+               return false;\r
+       }       \r
+       \r
+       static int delay(const std::wstring& filters)\r
+       {\r
+               return is_double_rate(filters) ? 1 : 1;\r
+       }\r
+\r
+       int delay() const\r
+       {\r
+               return delay(filter_str());\r
+       }\r
+\r
+       bool is_double_rate() const\r
+       {\r
+               return is_double_rate(filter_str());\r
+       }\r
+       \r
+       bool is_deinterlacing() const\r
+       {\r
+               return is_deinterlacing(filter_str());\r
+       }\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/filter/parallel_yadif.cpp b/modules/ffmpeg/producer/filter/parallel_yadif.cpp
new file mode 100644 (file)
index 0000000..b638842
--- /dev/null
@@ -0,0 +1,161 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../StdAfx.h"\r
+\r
+#include "parallel_yadif.h"\r
+\r
+#include <common/log/log.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libavfilter/avfilter.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+#include <tbb/parallel_for.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/thread/once.hpp>\r
+\r
+typedef struct {\r
+    int mode;\r
+    int parity;\r
+    int frame_pending;\r
+    int auto_enable;\r
+    AVFilterBufferRef *cur;\r
+    AVFilterBufferRef *next;\r
+    AVFilterBufferRef *prev;\r
+    AVFilterBufferRef *out;\r
+    void (*filter_line)(uint8_t *dst,\r
+                        uint8_t *prev, uint8_t *cur, uint8_t *next,\r
+                        int w, int prefs, int mrefs, int parity, int mode);\r
+    //const AVPixFmtDescriptor *csp;\r
+} YADIFContext;\r
+\r
+struct parallel_yadif_context\r
+{\r
+       struct arg\r
+       {\r
+               uint8_t *dst;\r
+               uint8_t *prev;\r
+               uint8_t *cur; \r
+               uint8_t *next; \r
+               int w; \r
+               int prefs; \r
+               int mrefs;\r
+               int parity;\r
+               int mode;\r
+       };\r
+\r
+       arg     args[1080];\r
+       int     index;\r
+       int last_index;\r
+\r
+       parallel_yadif_context() : index(0){}\r
+};\r
+\r
+void (*org_yadif_filter_line)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = 0;\r
+\r
+void parallel_yadif_filter_line(parallel_yadif_context& ctx, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode)\r
+{\r
+       parallel_yadif_context::arg arg = {dst, prev, cur, next, w, prefs, mrefs, parity, mode};\r
+       ctx.args[ctx.index++] = arg;\r
+       \r
+       if(ctx.index == ctx.last_index)\r
+       {               \r
+               tbb::parallel_for(tbb::blocked_range<size_t>(0, ctx.index), [=](const tbb::blocked_range<size_t>& r)\r
+               {\r
+                       for(auto n = r.begin(); n != r.end(); ++n)\r
+                               org_yadif_filter_line(ctx.args[n].dst, ctx.args[n].prev, ctx.args[n].cur, ctx.args[n].next, ctx.args[n].w, ctx.args[n].prefs, ctx.args[n].mrefs, ctx.args[n].parity, ctx.args[n].mode);\r
+               });\r
+               ctx.index = 0;\r
+       }\r
+}\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+tbb::concurrent_bounded_queue<decltype(org_yadif_filter_line)> parallel_line_func_pool;\r
+std::array<parallel_yadif_context, 18> ctxs;\r
+\r
+#define RENAME(a) f ## a\r
+\r
+#define ff(x) \\r
+void RENAME(x)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) \\r
+{\\r
+       parallel_yadif_filter_line(ctxs[x], dst, prev, cur, next, w, prefs, mrefs, parity, mode);\\r
+}\r
+\r
+ff(0); ff(1); ff(2); ff(3); ff(4); ff(5); ff(6); ff(7); ff(8); ff(9); ff(10); ff(11); ff(12); ff(13); ff(14); ff(15); ff(16); ff(17);\r
+\r
+void (*fs[])(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = \r
+{f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17};\r
+\r
+\r
+void init_pool()\r
+{\r
+       for(int n = 0; n < sizeof(fs)/sizeof(fs[0]); ++n)\r
+               parallel_line_func_pool.push(fs[n]);\r
+}\r
+\r
+void return_parallel_yadif(void* func)\r
+{\r
+       if(func != nullptr)\r
+               parallel_line_func_pool.push(reinterpret_cast<decltype(fs[0])>(func));\r
+}\r
+\r
+std::shared_ptr<void> make_parallel_yadif(AVFilterContext* ctx)\r
+{\r
+       static boost::once_flag flag = BOOST_ONCE_INIT;\r
+       boost::call_once(&init_pool, flag);\r
+\r
+       YADIFContext* yadif = (YADIFContext*)ctx->priv;\r
+       org_yadif_filter_line = yadif->filter_line; // Data race is not a problem.\r
+       \r
+       decltype(org_yadif_filter_line) func = nullptr;\r
+       if(!parallel_line_func_pool.try_pop(func))      \r
+               CASPAR_LOG(warning) << "Not enough scalable-yadif context instances. Running non-scalable";\r
+       else\r
+       {\r
+               int index = 0;\r
+               while(index < sizeof(fs)/sizeof(fs[0]) && fs[index] != func)\r
+                       ++index;\r
+\r
+               ctxs[index].last_index = 0;\r
+               for (int y = 0; y < ctx->inputs[0]->h; y++)\r
+               {\r
+            if ((y ^ yadif->parity) & 1)\r
+                               ++ctxs[index].last_index;\r
+               }\r
+\r
+               yadif->filter_line = func;\r
+       }\r
+\r
+       return std::shared_ptr<void>(func, return_parallel_yadif);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/filter/parallel_yadif.h b/modules/ffmpeg/producer/filter/parallel_yadif.h
new file mode 100644 (file)
index 0000000..6c2a3b8
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <memory>\r
+\r
+struct AVFilterContext;\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+std::shared_ptr<void> make_parallel_yadif(AVFilterContext* ctx);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp b/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp
new file mode 100644 (file)
index 0000000..aa35e0a
--- /dev/null
@@ -0,0 +1,429 @@
+#include "../../../StdAfx.h"\r
+\r
+#include "scalable_yadif.h"\r
+\r
+\r
+/*
+ * Copyright (C) 2006-2010 Michael Niedermayer <michaelni@gmx.at>
+ *               2010      James Darnley <james.darnley@gmail.com>
+ *
+ * FFmpeg 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+\r
+#pragma warning(push, 0)
+
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct {
+    /**
+     * 0: send 1 frame for each frame
+     * 1: send 1 frame for each field
+     * 2: like 0 but skips spatial interlacing check
+     * 3: like 1 but skips spatial interlacing check
+     */
+    int mode;
+
+    /**
+     *  0: bottom field first
+     *  1: top field first
+     * -1: auto-detection
+     */
+    int parity;
+
+    int frame_pending;
+
+    /**
+     *  0: deinterlace all frames
+     *  1: only deinterlace frames marked as interlaced
+     */
+    int auto_enable;
+
+    AVFilterBufferRef *cur;
+    AVFilterBufferRef *next;
+    AVFilterBufferRef *prev;
+    AVFilterBufferRef *out;
+    void (*filter_line)(uint8_t *dst,
+                        uint8_t *prev, uint8_t *cur, uint8_t *next,
+                        int w, int prefs, int mrefs, int parity, int mode);
+
+    const AVPixFmtDescriptor *csp;
+} YADIFContext;
+
+#define CHECK(j)\
+    {   int score = FFABS(cur[mrefs-1+(j)] - cur[prefs-1-(j)])\
+                  + FFABS(cur[mrefs  +(j)] - cur[prefs  -(j)])\
+                  + FFABS(cur[mrefs+1+(j)] - cur[prefs+1-(j)]);\
+        if (score < spatial_score) {\
+            spatial_score= score;\
+            spatial_pred= (cur[mrefs  +(j)] + cur[prefs  -(j)])>>1;\
+
+#define FILTER \
+    for (x = 0;  x < w; x++) { \
+        int c = cur[mrefs]; \
+        int d = (prev2[0] + next2[0])>>1; \
+        int e = cur[prefs]; \
+        int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
+        int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e) )>>1; \
+        int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e) )>>1; \
+        int diff = FFMAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2); \
+        int spatial_pred = (c+e)>>1; \
+        int spatial_score = FFABS(cur[mrefs-1] - cur[prefs-1]) + FFABS(c-e) \
+                          + FFABS(cur[mrefs+1] - cur[prefs+1]) - 1; \
+ \
+        CHECK(-1) CHECK(-2) }} }} \
+        CHECK( 1) CHECK( 2) }} }} \
+ \
+        if (mode < 2) { \
+            int b = (prev2[2*mrefs] + next2[2*mrefs])>>1; \
+            int f = (prev2[2*prefs] + next2[2*prefs])>>1; \
+            int max = FFMAX3(d-e, d-c, FFMIN(b-c, f-e)); \
+            int min = FFMIN3(d-e, d-c, FFMAX(b-c, f-e)); \
+ \
+            diff = FFMAX3(diff, min, -max); \
+        } \
+ \
+        if (spatial_pred > d + diff) \
+           spatial_pred = d + diff; \
+        else if (spatial_pred < d - diff) \
+           spatial_pred = d - diff; \
+ \
+        dst[0] = spatial_pred; \
+ \
+        dst++; \
+        cur++; \
+        prev++; \
+        next++; \
+        prev2++; \
+        next2++; \
+    }
+
+void filter_line_c(uint8_t *dst,
+                          uint8_t *prev, uint8_t *cur, uint8_t *next,
+                          int w, int prefs, int mrefs, int parity, int mode)
+{
+    int x;
+    uint8_t *prev2 = parity ? prev : cur ;
+    uint8_t *next2 = parity ? cur  : next;
+
+    FILTER
+}
+
+void filter_line_c_16bit(uint16_t *dst,
+                                uint16_t *prev, uint16_t *cur, uint16_t *next,
+                                int w, int prefs, int mrefs, int parity, int mode)
+{
+    int x;
+    uint16_t *prev2 = parity ? prev : cur ;
+    uint16_t *next2 = parity ? cur  : next;
+    mrefs /= 2;
+    prefs /= 2;
+
+    FILTER
+}
+
+void filter(AVFilterContext *ctx, AVFilterBufferRef *dstpic,
+                   int parity, int tff)
+{
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+    int y, i;
+
+    for (i = 0; i < yadif->csp->nb_components; i++) {
+        int w = dstpic->video->w;
+        int h = dstpic->video->h;
+        int refs = yadif->cur->linesize[i];
+        int df = (yadif->csp->comp[i].depth_minus1+1) / 8;
+
+        if (i) {
+        /* Why is this not part of the per-plane description thing? */
+            w >>= yadif->csp->log2_chroma_w;
+            h >>= yadif->csp->log2_chroma_h;
+        }
+
+        for (y = 0; y < h; y++) {
+            if ((y ^ parity) & 1) {
+                uint8_t *prev = &yadif->prev->data[i][y*refs];
+                uint8_t *cur  = &yadif->cur ->data[i][y*refs];
+                uint8_t *next = &yadif->next->data[i][y*refs];
+                uint8_t *dst  = &dstpic->data[i][y*dstpic->linesize[i]];
+                int     mode  = y==1 || y+2==h ? 2 : yadif->mode;
+                yadif->filter_line(dst, prev, cur, next, w, y+1<h ? refs : -refs, y ? -refs : refs, parity ^ tff, mode);
+            } else {
+                memcpy(&dstpic->data[i][y*dstpic->linesize[i]],
+                       &yadif->cur->data[i][y*refs], w*df);
+            }
+        }
+    }
+    //__asm__ volatile("emms \n\t" : : : "memory");
+}
+
+AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w, int h)
+{
+    AVFilterBufferRef *picref;
+    int width = FFALIGN(w, 32);
+    int height= FFALIGN(h+2, 32);
+    int i;
+
+    picref = avfilter_default_get_video_buffer(link, perms, width, height);
+
+    picref->video->w = w;
+    picref->video->h = h;
+
+    for (i = 0; i < 3; i++)
+        picref->data[i] += picref->linesize[i];
+
+    return picref;
+}
+
+void return_frame(AVFilterContext *ctx, int is_second)
+{
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+    AVFilterLink *link= ctx->outputs[0];
+    int tff;
+
+    if (yadif->parity == -1) {
+        tff = yadif->cur->video->interlaced ?
+            yadif->cur->video->top_field_first : 1;
+    } else {
+        tff = yadif->parity^1;
+    }
+
+    if (is_second)
+        yadif->out = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE |
+                                               AV_PERM_REUSE, link->w, link->h);
+
+    if (!yadif->csp)
+        yadif->csp = &av_pix_fmt_descriptors[link->format];
+    if (yadif->csp->comp[0].depth_minus1 == 15)
+        yadif->filter_line = (decltype(yadif->filter_line))filter_line_c_16bit;
+
+    filter(ctx, yadif->out, tff ^ !is_second, tff);
+
+    if (is_second) {
+        if (yadif->next->pts != AV_NOPTS_VALUE &&
+            yadif->cur->pts != AV_NOPTS_VALUE) {
+            yadif->out->pts =
+                (yadif->next->pts&yadif->cur->pts) +
+                ((yadif->next->pts^yadif->cur->pts)>>1);
+        } else {
+            yadif->out->pts = AV_NOPTS_VALUE;
+        }
+        avfilter_start_frame(ctx->outputs[0], yadif->out);
+    }
+    avfilter_draw_slice(ctx->outputs[0], 0, link->h, 1);
+    avfilter_end_frame(ctx->outputs[0]);
+
+    yadif->frame_pending = (yadif->mode&1) && !is_second;
+}
+
+void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+{
+    AVFilterContext *ctx = link->dst;
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+
+    if (yadif->frame_pending)
+        return_frame(ctx, 1);
+
+    if (yadif->prev)
+        avfilter_unref_buffer(yadif->prev);
+    yadif->prev = yadif->cur;
+    yadif->cur  = yadif->next;
+    yadif->next = picref;
+
+    if (!yadif->cur)
+        return;
+
+    if (yadif->auto_enable && !yadif->cur->video->interlaced) {
+        yadif->out  = avfilter_ref_buffer(yadif->cur, AV_PERM_READ);
+        avfilter_unref_buffer(yadif->prev);
+        yadif->prev = NULL;
+        avfilter_start_frame(ctx->outputs[0], yadif->out);
+        return;
+    }
+
+    if (!yadif->prev)
+        yadif->prev = avfilter_ref_buffer(yadif->cur, AV_PERM_READ);
+
+    yadif->out = avfilter_get_video_buffer(ctx->outputs[0], AV_PERM_WRITE | AV_PERM_PRESERVE |
+                                       AV_PERM_REUSE, link->w, link->h);
+
+    avfilter_copy_buffer_ref_props(yadif->out, yadif->cur);
+    yadif->out->video->interlaced = 0;
+    avfilter_start_frame(ctx->outputs[0], yadif->out);
+}
+
+void end_frame(AVFilterLink *link)
+{
+    AVFilterContext *ctx = link->dst;
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+
+    if (!yadif->out)
+        return;
+
+    if (yadif->auto_enable && !yadif->cur->video->interlaced) {
+        avfilter_draw_slice(ctx->outputs[0], 0, link->h, 1);
+        avfilter_end_frame(ctx->outputs[0]);
+        return;
+    }
+
+    return_frame(ctx, 0);
+}
+
+int request_frame(AVFilterLink *link)
+{
+    AVFilterContext *ctx = link->src;
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+
+    if (yadif->frame_pending) {
+        return_frame(ctx, 1);
+        return 0;
+    }
+
+    do {
+        int ret;
+               ret = avfilter_request_frame(link->src->inputs[0]);
+        if (ret)
+            return ret;
+    } while (!yadif->cur);
+
+    return 0;
+}
+
+int poll_frame(AVFilterLink *link)
+{
+    YADIFContext *yadif = (YADIFContext*)link->src->priv;
+    int ret, val;
+
+    if (yadif->frame_pending)
+        return 1;
+
+    val = avfilter_poll_frame(link->src->inputs[0]);
+
+    if (val==1 && !yadif->next) { //FIXME change API to not requre this red tape
+        if ((ret = avfilter_request_frame(link->src->inputs[0])) < 0)
+            return ret;
+        val = avfilter_poll_frame(link->src->inputs[0]);
+    }
+    assert(yadif->next || !val);
+
+    if (yadif->auto_enable && yadif->next && !yadif->next->video->interlaced)
+        return val;
+
+    return val * ((yadif->mode&1)+1);
+}
+
+void uninit(AVFilterContext *ctx)
+{
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+
+    if (yadif->prev) avfilter_unref_buffer(yadif->prev);
+    if (yadif->cur ) avfilter_unref_buffer(yadif->cur );
+    if (yadif->next) avfilter_unref_buffer(yadif->next);
+}
+
+int query_formats(AVFilterContext *ctx)
+{
+    static const enum PixelFormat pix_fmts[] = {
+        PIX_FMT_YUV420P,
+        PIX_FMT_YUV422P,
+        PIX_FMT_YUV444P,
+        PIX_FMT_YUV410P,
+        PIX_FMT_YUV411P,
+        PIX_FMT_GRAY8,
+        PIX_FMT_YUVJ420P,
+        PIX_FMT_YUVJ422P,
+        PIX_FMT_YUVJ444P,
+        AV_NE( PIX_FMT_GRAY16BE, PIX_FMT_GRAY16LE ),
+        PIX_FMT_YUV440P,
+        PIX_FMT_YUVJ440P,
+        AV_NE( PIX_FMT_YUV420P16BE, PIX_FMT_YUV420P16LE ),
+        AV_NE( PIX_FMT_YUV422P16BE, PIX_FMT_YUV422P16LE ),
+        AV_NE( PIX_FMT_YUV444P16BE, PIX_FMT_YUV444P16LE ),
+        PIX_FMT_NONE
+    };
+
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list((const int*)pix_fmts));
+
+    return 0;
+}
+
+int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+    YADIFContext *yadif = (YADIFContext*)ctx->priv;
+    av_unused int cpu_flags = av_get_cpu_flags();
+
+    yadif->mode = 0;
+    yadif->parity = -1;
+    yadif->auto_enable = 0;
+    yadif->csp = NULL;
+
+    if (args) sscanf(args, "%d:%d:%d", &yadif->mode, &yadif->parity, &yadif->auto_enable);
+
+       \r
+       auto module = LoadLibrary(L"avfilter-2.dll");\r
+       static std::shared_ptr<void> lib(module, FreeLibrary);\r
+    yadif->filter_line = (decltype(yadif->filter_line))(GetProcAddress(module, "ff_yadif_filter_line_ssse3"));
+
+    //yadif->filter_line = filter_line_c;
+    //if (HAVE_SSSE3 && cpu_flags & AV_CPU_FLAG_SSSE3)
+    //    yadif->filter_line = ff_yadif_filter_line_ssse3;
+    //else if (HAVE_SSE && cpu_flags & AV_CPU_FLAG_SSE2)
+    //    yadif->filter_line = ff_yadif_filter_line_sse2;
+    //else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX)
+    //    yadif->filter_line = ff_yadif_filter_line_mmx;
+
+    av_log(ctx, AV_LOG_INFO, "mode:%d parity:%d auto_enable:%d\n", yadif->mode, yadif->parity, yadif->auto_enable);
+
+    return 0;
+}
+
+void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
+
+void register_scalable_yadif()
+{
+       static AVFilter avfilter_vf_syadif;
+    avfilter_vf_syadif.name          = "syadif";
+    avfilter_vf_syadif .description   = "Deinterlace the input image";
+
+    avfilter_vf_syadif.priv_size     = sizeof(YADIFContext);
+    avfilter_vf_syadif.init          = init;
+    avfilter_vf_syadif.uninit        = uninit;
+    avfilter_vf_syadif.query_formats = query_formats;
+
+       static AVFilterPad inputs[2];
+
+       inputs[0].name                          = "default";         
+       inputs[0].type                          = AVMEDIA_TYPE_VIDEO,
+    inputs[0].start_frame              = start_frame;
+    inputs[0].get_video_buffer = get_video_buffer;
+    inputs[0].draw_slice               = null_draw_slice;
+    inputs[0].end_frame                        = end_frame;
+       inputs[1].name                          = nullptr;
+       
+       avfilter_vf_syadif.inputs = inputs;
+
+       static AVFilterPad outputs[2];
+
+       outputs[0].name                         = "default";
+       outputs[0].type                         = AVMEDIA_TYPE_VIDEO;
+       outputs[0].poll_frame           = poll_frame;
+       outputs[0].request_frame        = request_frame;
+       outputs[1].name                         = nullptr;
+       
+       avfilter_vf_syadif.outputs = outputs;
+       
+       avfilter_register(&avfilter_vf_syadif);
+};
diff --git a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h b/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h
new file mode 100644 (file)
index 0000000..e734057
--- /dev/null
@@ -0,0 +1,23 @@
+#pragma once\r
+\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS
+       #include <libavutil/cpu.h>
+       #include <libavutil/common.h>
+       #include <libavutil/pixdesc.h>
+       #include <libavfilter/avfilter.h>\r
+}\r
+\r
+int init(AVFilterContext *ctx, const char *args, void *opaque);\r
+void uninit(AVFilterContext *ctx);\r
+int query_formats(AVFilterContext *ctx);\r
+int poll_frame(AVFilterLink *link);\r
+int request_frame(AVFilterLink *link);\r
+void start_frame(AVFilterLink *link, AVFilterBufferRef *picref);\r
+void end_frame(AVFilterLink *link);\r
+void return_frame(AVFilterContext *ctx, int is_second);\r
+AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w, int h);\r
+\r
+void register_scalable_yadif();
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/input/input.cpp b/modules/ffmpeg/producer/input/input.cpp
new file mode 100644 (file)
index 0000000..849af4f
--- /dev/null
@@ -0,0 +1,289 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "input.h"\r
+\r
+#include "../util/util.h"\r
+#include "../../ffmpeg_error.h"\r
+#include "../../ffmpeg.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <common/diagnostics/graph.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/concurrency/future_util.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/exception/win32_exception.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/atomic.h>\r
+#include <tbb/recursive_mutex.h>\r
+\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/thread/condition_variable.hpp>\r
+#include <boost/thread/mutex.hpp>\r
+#include <boost/thread/thread.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavformat/avformat.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+static const size_t MAX_BUFFER_COUNT = 100;\r
+static const size_t MIN_BUFFER_COUNT = 50;\r
+static const size_t MAX_BUFFER_SIZE  = 64 * 1000000;\r
+\r
+namespace caspar { namespace ffmpeg {\r
+               \r
+struct input::implementation : boost::noncopyable\r
+{              \r
+       const safe_ptr<diagnostics::graph>                                                      graph_;\r
+\r
+       const safe_ptr<AVFormatContext>                                                         format_context_; // Destroy this last\r
+       const int                                                                                                       default_stream_index_;\r
+                       \r
+       const std::wstring                                                                                      filename_;\r
+       const uint32_t                                                                                          start_;         \r
+       const uint32_t                                                                                          length_;\r
+       const bool                                                                                                      thumbnail_mode_;\r
+       tbb::atomic<bool>                                                                                       loop_;\r
+       uint32_t                                                                                                        frame_number_;\r
+       \r
+       tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>>        buffer_;\r
+       tbb::atomic<size_t>                                                                                     buffer_size_;\r
+               \r
+       executor                                                                                                        executor_;\r
+       \r
+       explicit implementation(const safe_ptr<diagnostics::graph> graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode) \r
+               : graph_(graph)\r
+               , format_context_(open_input(filename))         \r
+               , default_stream_index_(av_find_default_stream_index(format_context_.get()))\r
+               , filename_(filename)\r
+               , start_(start)\r
+               , length_(length)\r
+               , thumbnail_mode_(thumbnail_mode)\r
+               , frame_number_(0)\r
+               , executor_(print())\r
+       {\r
+               if (thumbnail_mode_)\r
+                       executor_.invoke([]\r
+                       {\r
+                               disable_logging_for_thread();\r
+                       });\r
+\r
+               loop_                   = loop;\r
+               buffer_size_    = 0;\r
+\r
+               if(start_ > 0)                  \r
+                       queued_seek(start_);\r
+                                                               \r
+               graph_->set_color("seek", diagnostics::color(1.0f, 0.5f, 0.0f));        \r
+               graph_->set_color("buffer-count", diagnostics::color(0.7f, 0.4f, 0.4f));\r
+               graph_->set_color("buffer-size", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
+\r
+               tick();\r
+       }\r
+       \r
+       bool try_pop(std::shared_ptr<AVPacket>& packet)\r
+       {\r
+               auto result = buffer_.try_pop(packet);\r
+               \r
+               if(result)\r
+               {\r
+                       if(packet)\r
+                               buffer_size_ -= packet->size;\r
+                       tick();\r
+               }\r
+\r
+               graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);\r
+               graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));\r
+               \r
+               return result;\r
+       }\r
+\r
+       std::ptrdiff_t get_max_buffer_count() const\r
+       {\r
+               return thumbnail_mode_ ? 1 : MAX_BUFFER_COUNT;\r
+       }\r
+\r
+       std::ptrdiff_t get_min_buffer_count() const\r
+       {\r
+               return thumbnail_mode_ ? 0 : MIN_BUFFER_COUNT;\r
+       }\r
+\r
+       boost::unique_future<bool> seek(uint32_t target)\r
+       {\r
+               if (!executor_.is_running())\r
+                       return wrap_as_future(false);\r
+\r
+               return executor_.begin_invoke([=]() -> bool\r
+               {\r
+                       std::shared_ptr<AVPacket> packet;\r
+                       while(buffer_.try_pop(packet) && packet)\r
+                               buffer_size_ -= packet->size;\r
+\r
+                       queued_seek(target);\r
+\r
+                       tick();\r
+\r
+                       return true;\r
+               }, high_priority);\r
+       }\r
+       \r
+       std::wstring print() const\r
+       {\r
+               return L"ffmpeg_input[" + filename_ + L")]";\r
+       }\r
+       \r
+       bool full() const\r
+       {\r
+               return (buffer_size_ > MAX_BUFFER_SIZE || buffer_.size() > get_max_buffer_count()) && buffer_.size() > get_min_buffer_count();\r
+       }\r
+\r
+       void tick()\r
+       {       \r
+               if(!executor_.is_running())\r
+                       return;\r
+               \r
+               executor_.begin_invoke([this]\r
+               {                       \r
+                       if(full())\r
+                               return;\r
+\r
+                       try\r
+                       {\r
+                               auto packet = create_packet();\r
+               \r
+                               auto ret = av_read_frame(format_context_.get(), packet.get()); // packet is only valid until next call of av_read_frame. Use av_dup_packet to extend its life.  \r
+               \r
+                               if(is_eof(ret))                                                                                                              \r
+                               {\r
+                                       frame_number_   = 0;\r
+\r
+                                       if(loop_)\r
+                                       {\r
+                                               queued_seek(start_);\r
+                                               graph_->set_tag("seek");                \r
+                                               CASPAR_LOG(trace) << print() << " Looping.";                    \r
+                                       }               \r
+                                       else\r
+                                               executor_.stop();\r
+                               }\r
+                               else\r
+                               {               \r
+                                       THROW_ON_ERROR(ret, "av_read_frame", print());\r
+\r
+                                       if(packet->stream_index == default_stream_index_)\r
+                                               ++frame_number_;\r
+\r
+                                       THROW_ON_ERROR2(av_dup_packet(packet.get()), print());\r
+                               \r
+                                       // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
+                                       auto size = packet->size;\r
+                                       auto data = packet->data;\r
+                       \r
+                                       packet = safe_ptr<AVPacket>(packet.get(), [packet, size, data](AVPacket*)\r
+                                       {\r
+                                               packet->size = size;\r
+                                               packet->data = data;                            \r
+                                       });\r
+\r
+                                       buffer_.try_push(packet);\r
+                                       buffer_size_ += packet->size;\r
+                               \r
+                                       graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);\r
+                                       graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));\r
+                               }       \r
+               \r
+                               tick();         \r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               if (!thumbnail_mode_)\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               executor_.stop();\r
+                       }\r
+               });\r
+       }       \r
+                       \r
+       void queued_seek(const uint32_t target)\r
+       {       \r
+               if (!thumbnail_mode_)\r
+                       CASPAR_LOG(debug) << print() << " Seeking: " << target;\r
+\r
+               int flags = AVSEEK_FLAG_FRAME;\r
+               if(target == 0)\r
+               {\r
+                       // Fix VP6 seeking\r
+                       int vid_stream_index = av_find_best_stream(format_context_.get(), AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
+                       if(vid_stream_index >= 0)\r
+                       {\r
+                               auto codec_id = format_context_->streams[vid_stream_index]->codec->codec_id;\r
+                               if(codec_id == CODEC_ID_VP6A || codec_id == CODEC_ID_VP6F || codec_id == CODEC_ID_VP6)\r
+                                       flags = AVSEEK_FLAG_BYTE;\r
+                       }\r
+               }\r
+               \r
+               auto stream = format_context_->streams[default_stream_index_];\r
+               auto codec  = stream->codec;\r
+               auto fixed_target = (target*stream->time_base.den*codec->time_base.num)/(stream->time_base.num*codec->time_base.den)*codec->ticks_per_frame;\r
+               \r
+               THROW_ON_ERROR2(avformat_seek_file(format_context_.get(), default_stream_index_, std::numeric_limits<int64_t>::min(), fixed_target, std::numeric_limits<int64_t>::max(), 0), print());          \r
+               \r
+               auto flush_packet       = create_packet();\r
+               flush_packet->data      = nullptr;\r
+               flush_packet->size      = 0;\r
+               flush_packet->pos       = target;\r
+\r
+               buffer_.push(flush_packet);\r
+       }       \r
+\r
+       bool is_eof(int ret)\r
+       {\r
+               if(ret == AVERROR(EIO))\r
+                       CASPAR_LOG(trace) << print() << " Received EIO, assuming EOF. ";\r
+               if(ret == AVERROR_EOF)\r
+                       CASPAR_LOG(trace) << print() << " Received EOF. ";\r
+\r
+               return ret == AVERROR_EOF || ret == AVERROR(EIO) || frame_number_ >= length_; // av_read_frame doesn't always correctly return AVERROR_EOF;\r
+       }\r
+};\r
+\r
+input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode) \r
+       : impl_(new implementation(graph, filename, loop, start, length, thumbnail_mode)){}\r
+bool input::eof() const {return !impl_->executor_.is_running();}\r
+bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
+safe_ptr<AVFormatContext> input::context(){return impl_->format_context_;}\r
+void input::loop(bool value){impl_->loop_ = value;}\r
+bool input::loop() const{return impl_->loop_;}\r
+boost::unique_future<bool> input::seek(uint32_t target){return impl_->seek(target);}\r
+}}\r
diff --git a/modules/ffmpeg/producer/input/input.h b/modules/ffmpeg/producer/input/input.h
new file mode 100644 (file)
index 0000000..69984c6
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <memory>\r
+#include <string>\r
+#include <cstdint>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+struct AVFormatContext;\r
+struct AVPacket;\r
+\r
+namespace caspar {\r
+\r
+namespace diagnostics {\r
+\r
+class graph;\r
+\r
+}\r
+        \r
+namespace ffmpeg {\r
+\r
+class input : boost::noncopyable\r
+{\r
+public:\r
+       explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode);\r
+\r
+       bool try_pop(std::shared_ptr<AVPacket>& packet);\r
+       bool eof() const;\r
+\r
+       void loop(bool value);\r
+       bool loop() const;\r
+\r
+       boost::unique_future<bool> seek(uint32_t target);\r
+\r
+       safe_ptr<AVFormatContext> context();\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+\r
+       \r
+}}\r
diff --git a/modules/ffmpeg/producer/muxer/display_mode.h b/modules/ffmpeg/producer/muxer/display_mode.h
new file mode 100644 (file)
index 0000000..201074d
--- /dev/null
@@ -0,0 +1,110 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/video_format.h>\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+struct display_mode\r
+{\r
+       enum type\r
+       {\r
+               simple,\r
+               duplicate,\r
+               half,\r
+               interlace,\r
+               deinterlace_bob,\r
+               deinterlace_bob_reinterlace,\r
+               deinterlace,\r
+               count,\r
+               invalid\r
+       };\r
+\r
+       static std::wstring print(display_mode::type value)\r
+       {\r
+               switch(value)\r
+               {\r
+                       case simple:                                            return L"simple";\r
+                       case duplicate:                                         return L"duplicate";\r
+                       case half:                                                      return L"half";\r
+                       case interlace:                                         return L"interlace";\r
+                       case deinterlace_bob:                           return L"deinterlace_bob";\r
+                       case deinterlace_bob_reinterlace:       return L"deinterlace_bob_reinterlace";\r
+                       case deinterlace:                                       return L"deinterlace";\r
+                       default:                                                        return L"invalid";\r
+               }\r
+       }\r
+};\r
+\r
+static display_mode::type get_display_mode(const core::field_mode::type in_mode, double in_fps, const core::field_mode::type out_mode, double out_fps)\r
+{              \r
+       static const auto epsilon = 2.0;\r
+\r
+       if(in_fps < 20.0 || in_fps > 80.0)\r
+       {\r
+               //if(out_mode != core::field_mode::progressive && in_mode == core::field_mode::progressive)\r
+               //      return display_mode::interlace;\r
+               \r
+               if(out_mode == core::field_mode::progressive && in_mode != core::field_mode::progressive)\r
+               {\r
+                       if(in_fps < 35.0)\r
+                               return display_mode::deinterlace;\r
+                       else\r
+                               return display_mode::deinterlace_bob;\r
+               }\r
+       }\r
+\r
+       if(std::abs(in_fps - out_fps) < epsilon)\r
+       {\r
+               if(in_mode != core::field_mode::progressive && out_mode == core::field_mode::progressive)\r
+                       return display_mode::deinterlace;\r
+               //else if(in_mode == core::field_mode::progressive && out_mode != core::field_mode::progressive)\r
+               //      simple(); // interlace_duplicate();\r
+               else\r
+                       return display_mode::simple;\r
+       }\r
+       else if(std::abs(in_fps/2.0 - out_fps) < epsilon)\r
+       {\r
+               if(in_mode != core::field_mode::progressive)\r
+                       return display_mode::invalid;\r
+\r
+               if(out_mode != core::field_mode::progressive)\r
+                       return display_mode::interlace;\r
+               else\r
+                       return display_mode::half;\r
+       }\r
+       else if(std::abs(in_fps - out_fps/2.0) < epsilon)\r
+       {\r
+               if(out_mode != core::field_mode::progressive)\r
+                       return display_mode::invalid;\r
+\r
+               if(in_mode != core::field_mode::progressive)\r
+                       return display_mode::deinterlace_bob;\r
+               else\r
+                       return display_mode::duplicate;\r
+       }\r
+\r
+       return display_mode::invalid;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/muxer/frame_muxer.cpp b/modules/ffmpeg/producer/muxer/frame_muxer.cpp
new file mode 100644 (file)
index 0000000..bb9114b
--- /dev/null
@@ -0,0 +1,390 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../StdAfx.h"\r
+\r
+#include "frame_muxer.h"\r
+\r
+#include "../filter/filter.h"\r
+#include "../util/util.h"\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/env.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/log/log.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavcodec/avcodec.h>\r
+       #include <libavformat/avformat.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm_ext/push_back.hpp>\r
+#include <boost/algorithm/string/predicate.hpp>\r
+\r
+#include <deque>\r
+#include <queue>\r
+#include <vector>\r
+\r
+using namespace caspar::core;\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+struct frame_muxer::implementation : boost::noncopyable\r
+{      \r
+       std::queue<std::queue<safe_ptr<write_frame>>>   video_streams_;\r
+       std::queue<core::audio_buffer>                                  audio_streams_;\r
+       std::queue<safe_ptr<basic_frame>>                               frame_buffer_;\r
+       display_mode::type                                                              display_mode_;\r
+       const double                                                                    in_fps_;\r
+       const video_format_desc                                                 format_desc_;\r
+       bool                                                                                    auto_transcode_;\r
+       bool                                                                                    auto_deinterlace_;\r
+       \r
+       std::vector<size_t>                                                             audio_cadence_;\r
+                       \r
+       safe_ptr<core::frame_factory>                                   frame_factory_;\r
+       \r
+       filter                                                                                  filter_;\r
+       const std::wstring                                                              filter_str_;\r
+       const bool                                                                              thumbnail_mode_;\r
+       bool                                                                                    force_deinterlacing_;\r
+               \r
+       implementation(double in_fps, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filter_str, bool thumbnail_mode)\r
+               : display_mode_(display_mode::invalid)\r
+               , in_fps_(in_fps)\r
+               , format_desc_(frame_factory->get_video_format_desc())\r
+               , auto_transcode_(env::properties().get(L"configuration.auto-transcode", true))\r
+               , auto_deinterlace_(env::properties().get(L"configuration.auto-deinterlace", true))\r
+               , audio_cadence_(format_desc_.audio_cadence)\r
+               , frame_factory_(frame_factory)\r
+               , filter_str_(filter_str)\r
+               , thumbnail_mode_(thumbnail_mode)\r
+               , force_deinterlacing_(false)\r
+       {\r
+               video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
+               audio_streams_.push(core::audio_buffer());\r
+               \r
+               // Note: Uses 1 step rotated cadence for 1001 modes (1602, 1602, 1601, 1602, 1601)\r
+               // This cadence fills the audio mixer most optimally.\r
+               boost::range::rotate(audio_cadence_, std::end(audio_cadence_)-1);\r
+       }\r
+\r
+       void push(const std::shared_ptr<AVFrame>& video_frame, int hints)\r
+       {               \r
+               if(!video_frame)\r
+                       return;\r
+               \r
+               if(video_frame == flush_video())\r
+               {       \r
+                       video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
+               }\r
+               else if(video_frame == empty_video())\r
+               {\r
+                       video_streams_.back().push(make_safe<core::write_frame>(this));\r
+                       display_mode_ = display_mode::simple;\r
+               }\r
+               else\r
+               {\r
+                       bool deinterlace_hint = (hints & core::frame_producer::DEINTERLACE_HINT) != 0;\r
+               \r
+                       if(auto_deinterlace_ && force_deinterlacing_ != deinterlace_hint)\r
+                       {\r
+                               force_deinterlacing_ = deinterlace_hint;\r
+                               display_mode_ = display_mode::invalid;\r
+                       }\r
+\r
+                       if(display_mode_ == display_mode::invalid)\r
+                               update_display_mode(video_frame, force_deinterlacing_);\r
+                               \r
+                       if(hints & core::frame_producer::ALPHA_HINT)\r
+                               video_frame->format = make_alpha_format(video_frame->format);\r
+               \r
+                       auto format = video_frame->format;\r
+                       if(video_frame->format == CASPAR_PIX_FMT_LUMA) // CASPAR_PIX_FMT_LUMA is not valid for filter, change it to GRAY8\r
+                               video_frame->format = PIX_FMT_GRAY8;\r
+\r
+                       filter_.push(video_frame);\r
+                       BOOST_FOREACH(auto& av_frame, filter_.poll_all())\r
+                       {\r
+                               if(video_frame->format == PIX_FMT_GRAY8 && format == CASPAR_PIX_FMT_LUMA)\r
+                                       av_frame->format = format;\r
+\r
+                               video_streams_.back().push(make_write_frame(this, av_frame, frame_factory_, hints));\r
+                       }\r
+               }\r
+\r
+               if(video_streams_.back().size() > 32)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << source_info("frame_muxer") << msg_info("video-stream overflow. This can be caused by incorrect frame-rate. Check clip meta-data."));\r
+       }\r
+\r
+       void push(const std::shared_ptr<core::audio_buffer>& audio)\r
+       {\r
+               if(!audio)      \r
+                       return;\r
+\r
+               if(audio == flush_audio())\r
+               {\r
+                       audio_streams_.push(core::audio_buffer());\r
+               }\r
+               else if(audio == empty_audio())\r
+               {\r
+                       boost::range::push_back(audio_streams_.back(), core::audio_buffer(audio_cadence_.front(), 0));\r
+               }\r
+               else\r
+               {\r
+                       boost::range::push_back(audio_streams_.back(), *audio);\r
+               }\r
+\r
+               if(audio_streams_.back().size() > 32*audio_cadence_.front())\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << source_info("frame_muxer") << msg_info("audio-stream overflow. This can be caused by incorrect frame-rate. Check clip meta-data."));\r
+       }\r
+       \r
+       bool video_ready() const\r
+       {               \r
+               return video_streams_.size() > 1 || (video_streams_.size() >= audio_streams_.size() && video_ready2());\r
+       }\r
+       \r
+       bool audio_ready() const\r
+       {\r
+               return audio_streams_.size() > 1 || (audio_streams_.size() >= video_streams_.size() && audio_ready2());\r
+       }\r
+\r
+       bool video_ready2() const\r
+       {               \r
+               switch(display_mode_)\r
+               {\r
+               case display_mode::deinterlace_bob_reinterlace:                                 \r
+               case display_mode::interlace:   \r
+               case display_mode::half:\r
+                       return video_streams_.front().size() >= 2;\r
+               default:                                                                                \r
+                       return video_streams_.front().size() >= 1;\r
+               }\r
+       }\r
+       \r
+       bool audio_ready2() const\r
+       {\r
+               switch(display_mode_)\r
+               {\r
+               case display_mode::duplicate:                                   \r
+                       return audio_streams_.front().size()/2 >= audio_cadence_.front();\r
+               default:                                                                                \r
+                       return audio_streams_.front().size() >= audio_cadence_.front();\r
+               }\r
+       }\r
+               \r
+       std::shared_ptr<basic_frame> poll()\r
+       {\r
+               if(!frame_buffer_.empty())\r
+               {\r
+                       auto frame = frame_buffer_.front();\r
+                       frame_buffer_.pop();    \r
+                       return frame;\r
+               }\r
+\r
+               if(video_streams_.size() > 1 && audio_streams_.size() > 1 && (!video_ready2() || !audio_ready2()))\r
+               {\r
+                       if(!video_streams_.front().empty() || !audio_streams_.front().empty())\r
+                               CASPAR_LOG(trace) << "Truncating: " << video_streams_.front().size() << L" video-frames, " << audio_streams_.front().size() << L" audio-samples.";\r
+\r
+                       video_streams_.pop();\r
+                       audio_streams_.pop();\r
+               }\r
+\r
+               if(!video_ready2() || !audio_ready2() || display_mode_ == display_mode::invalid)\r
+                       return nullptr;\r
+                               \r
+               auto frame1                             = pop_video();\r
+               frame1->audio_data()    = pop_audio();\r
+\r
+               switch(display_mode_)\r
+               {\r
+               case display_mode::simple:                                              \r
+               case display_mode::deinterlace_bob:                             \r
+               case display_mode::deinterlace: \r
+                       {\r
+                               frame_buffer_.push(frame1);\r
+                               break;\r
+                       }\r
+               case display_mode::interlace:                                   \r
+               case display_mode::deinterlace_bob_reinterlace: \r
+                       {                               \r
+                               auto frame2 = pop_video();\r
+\r
+                               frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode));      \r
+                               break;\r
+                       }\r
+               case display_mode::duplicate:   \r
+                       {\r
+                               auto frame2                             = make_safe<core::write_frame>(*frame1);\r
+                               frame2->audio_data()    = pop_audio();\r
+\r
+                               frame_buffer_.push(frame1);\r
+                               frame_buffer_.push(frame2);\r
+                               break;\r
+                       }\r
+               case display_mode::half:        \r
+                       {                               \r
+                               pop_video(); // Throw away\r
+\r
+                               frame_buffer_.push(frame1);\r
+                               break;\r
+                       }\r
+               }\r
+               \r
+               return frame_buffer_.empty() ? nullptr : poll();\r
+       }\r
+       \r
+       safe_ptr<core::write_frame> pop_video()\r
+       {\r
+               auto frame = video_streams_.front().front();\r
+               video_streams_.front().pop();           \r
+               return frame;\r
+       }\r
+\r
+       core::audio_buffer pop_audio()\r
+       {\r
+               CASPAR_VERIFY(audio_streams_.front().size() >= audio_cadence_.front());\r
+\r
+               auto begin = audio_streams_.front().begin();\r
+               auto end   = begin + audio_cadence_.front();\r
+\r
+               core::audio_buffer samples(begin, end);\r
+               audio_streams_.front().erase(begin, end);\r
+               \r
+               boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+\r
+               return samples;\r
+       }\r
+                               \r
+       void update_display_mode(const std::shared_ptr<AVFrame>& frame, bool force_deinterlace)\r
+       {\r
+               std::wstring filter_str = filter_str_;\r
+\r
+               display_mode_ = display_mode::simple;\r
+               if(auto_transcode_)\r
+               {\r
+                       auto mode = get_mode(*frame);\r
+                       auto fps  = in_fps_;\r
+\r
+                       if(filter::is_deinterlacing(filter_str_))\r
+                               mode = core::field_mode::progressive;\r
+\r
+                       if(filter::is_double_rate(filter_str_))\r
+                               fps *= 2;\r
+                       \r
+                       display_mode_ = get_display_mode(mode, fps, format_desc_.field_mode, format_desc_.fps);\r
+                       \r
+                       if((frame->height != 480 || format_desc_.height != 486) && // don't deinterlace for NTSC DV\r
+                                       display_mode_ == display_mode::simple && mode != core::field_mode::progressive && format_desc_.field_mode != core::field_mode::progressive && \r
+                                       frame->height != static_cast<int>(format_desc_.height))\r
+                       {\r
+                               display_mode_ = display_mode::deinterlace_bob_reinterlace; // The frame will most likely be scaled, we need to deinterlace->reinterlace \r
+                       }\r
+\r
+                       if(force_deinterlace && mode != core::field_mode::progressive && \r
+                          display_mode_ != display_mode::deinterlace && \r
+                          display_mode_ != display_mode::deinterlace_bob && \r
+                          display_mode_ != display_mode::deinterlace_bob_reinterlace)                  \r
+                       {       \r
+                               if (!thumbnail_mode_)\r
+                                       CASPAR_LOG(info) << L"[frame_muxer] Automatically started non bob-deinterlacing. Consider starting producer with bob-deinterlacing (FILTER DEINTERLACE_BOB) for smoothest playback.";\r
+                               display_mode_ = display_mode::deinterlace;\r
+                       }\r
+\r
+                       if(display_mode_ == display_mode::deinterlace)\r
+                               filter_str = append_filter(filter_str, L"YADIF=0:-1");\r
+                       else if(display_mode_ == display_mode::deinterlace_bob || display_mode_ == display_mode::deinterlace_bob_reinterlace)\r
+                               filter_str = append_filter(filter_str, L"YADIF=1:-1");\r
+               }\r
+\r
+               if(display_mode_ == display_mode::invalid)\r
+               {\r
+                       if (!thumbnail_mode_)\r
+                               CASPAR_LOG(warning) << L"[frame_muxer] Auto-transcode: Failed to detect display-mode.";\r
+                       display_mode_ = display_mode::simple;\r
+               }\r
+                       \r
+               if(!boost::iequals(filter_.filter_str(), filter_str))\r
+               {\r
+                       for(int n = 0; n < filter_.delay(); ++n)\r
+                       {\r
+                               filter_.push(frame);\r
+                               auto av_frame = filter_.poll();\r
+                               if(av_frame)                                                    \r
+                                       video_streams_.back().push(make_write_frame(this, make_safe_ptr(av_frame), frame_factory_, 0));\r
+                       }\r
+                       filter_ = filter(filter_str);\r
+                       if (!thumbnail_mode_)\r
+                               CASPAR_LOG(info) << L"[frame_muxer] " << display_mode::print(display_mode_) << L" " << print_mode(frame->width, frame->height, in_fps_, frame->interlaced_frame > 0);\r
+               }\r
+       }\r
+       \r
+       uint32_t calc_nb_frames(uint32_t nb_frames) const\r
+       {\r
+               uint64_t nb_frames2 = nb_frames;\r
+               \r
+               if(filter_.is_double_rate()) // Take into account transformations in filter.\r
+                       nb_frames2 *= 2;\r
+\r
+               switch(display_mode_) // Take into account transformation in run.\r
+               {\r
+               case display_mode::deinterlace_bob_reinterlace:\r
+               case display_mode::interlace:   \r
+               case display_mode::half:\r
+                       nb_frames2 /= 2;\r
+                       break;\r
+               case display_mode::duplicate:\r
+                       nb_frames2 *= 2;\r
+                       break;\r
+               }\r
+\r
+               return static_cast<uint32_t>(nb_frames2);\r
+       }\r
+};\r
+\r
+frame_muxer::frame_muxer(double in_fps, const safe_ptr<core::frame_factory>& frame_factory, bool thumbnail_mode, const std::wstring& filter)\r
+       : impl_(new implementation(in_fps, frame_factory, filter, thumbnail_mode)){}\r
+void frame_muxer::push(const std::shared_ptr<AVFrame>& video_frame, int hints){impl_->push(video_frame, hints);}\r
+void frame_muxer::push(const std::shared_ptr<core::audio_buffer>& audio_samples){return impl_->push(audio_samples);}\r
+std::shared_ptr<basic_frame> frame_muxer::poll(){return impl_->poll();}\r
+uint32_t frame_muxer::calc_nb_frames(uint32_t nb_frames) const {return impl_->calc_nb_frames(nb_frames);}\r
+bool frame_muxer::video_ready() const{return impl_->video_ready();}\r
+bool frame_muxer::audio_ready() const{return impl_->audio_ready();}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/muxer/frame_muxer.h b/modules/ffmpeg/producer/muxer/frame_muxer.h
new file mode 100644 (file)
index 0000000..6d3671b
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "display_mode.h"\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/mixer/audio/audio_mixer.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <vector>\r
+\r
+struct AVFrame;\r
+\r
+namespace caspar { \r
+       \r
+namespace core {\r
+\r
+class write_frame;\r
+class basic_frame;\r
+struct frame_factory;\r
+\r
+}\r
+\r
+namespace ffmpeg {\r
+\r
+class frame_muxer : boost::noncopyable\r
+{\r
+public:\r
+       frame_muxer(double in_fps, const safe_ptr<core::frame_factory>& frame_factory, bool thumbnail_mode, const std::wstring& filter = L"");\r
+       \r
+       void push(const std::shared_ptr<AVFrame>& video_frame, int hints = 0);\r
+       void push(const std::shared_ptr<core::audio_buffer>& audio_samples);\r
+       \r
+       bool video_ready() const;\r
+       bool audio_ready() const;\r
+\r
+       std::shared_ptr<core::basic_frame> poll();\r
+\r
+       uint32_t calc_nb_frames(uint32_t nb_frames) const;\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/tbb_avcodec.cpp b/modules/ffmpeg/producer/tbb_avcodec.cpp
new file mode 100644 (file)
index 0000000..09ad9d5
--- /dev/null
@@ -0,0 +1,132 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "tbb_avcodec.h"\r
+\r
+#include <common/log/log.h>\r
+#include <common/env.h>\r
+#include <common/utility/assert.h>\r
+\r
+#include <tbb/task.h>\r
+#include <tbb/atomic.h>\r
+#include <tbb/parallel_for.h>\r
+#include <tbb/tbb_thread.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavformat/avformat.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar {\r
+               \r
+int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void *arg2), void* arg, int* ret, int count, int size)\r
+{\r
+       tbb::parallel_for(0, count, 1, [&](int i)\r
+       {\r
+        int r = func(s, (char*)arg + i*size);\r
+        if(ret) \r
+                       ret[i] = r;\r
+    });\r
+\r
+       return 0;\r
+}\r
+\r
+int thread_execute2(AVCodecContext* s, int (*func)(AVCodecContext* c2, void* arg2, int, int), void* arg, int* ret, int count)\r
+{      \r
+       tbb::atomic<int> counter;   \r
+    counter = 0;   \r
+\r
+       CASPAR_VERIFY(tbb::tbb_thread::hardware_concurrency() < 16);\r
+       // Note: this will probably only work when tbb::task_scheduler_init::num_threads() < 16.\r
+    tbb::parallel_for(tbb::blocked_range<int>(0, count, 2), [&](const tbb::blocked_range<int> &r)    \r
+    {   \r
+        int threadnr = counter++;   \r
+        for(int jobnr = r.begin(); jobnr != r.end(); ++jobnr)\r
+        {   \r
+            int r = func(s, arg, jobnr, threadnr);   \r
+            if (ret)   \r
+                ret[jobnr] = r;   \r
+        }\r
+        --counter;\r
+    });   \r
+\r
+    return 0;  \r
+}\r
+\r
+void thread_init(AVCodecContext* s)\r
+{\r
+       static const size_t MAX_THREADS = 16; // See mpegvideo.h\r
+       static int dummy_opaque;\r
+\r
+    s->active_thread_type = FF_THREAD_SLICE;\r
+       s->thread_opaque          = &dummy_opaque; \r
+    s->execute                   = thread_execute;\r
+    s->execute2                          = thread_execute2;\r
+    s->thread_count              = MAX_THREADS; // We are using a task-scheduler, so use as many "threads/tasks" as possible. \r
+\r
+       CASPAR_LOG(info) << "Initialized ffmpeg tbb context.";\r
+}\r
+\r
+void thread_free(AVCodecContext* s)\r
+{\r
+       if(!s->thread_opaque)\r
+               return;\r
+\r
+       s->thread_opaque = nullptr;\r
+       \r
+       CASPAR_LOG(info) << "Released ffmpeg tbb context.";\r
+}\r
+\r
+int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec)\r
+{\r
+       CodecID supported_codecs[] = {CODEC_ID_MPEG2VIDEO, CODEC_ID_PRORES, CODEC_ID_FFV1};\r
+\r
+       avctx->thread_count = 1;\r
+       // Some codecs don't like to have multiple multithreaded decoding instances. Only enable for those we know work.\r
+       if(std::find(std::begin(supported_codecs), std::end(supported_codecs), codec->id) != std::end(supported_codecs) && \r
+         (codec->capabilities & CODEC_CAP_SLICE_THREADS) && \r
+         (avctx->thread_type & FF_THREAD_SLICE)) \r
+       {\r
+               thread_init(avctx);\r
+       }       \r
+       // ff_thread_init will not be executed since thread_opaque != nullptr || thread_count == 1.\r
+       return avcodec_open(avctx, codec); \r
+}\r
+\r
+int tbb_avcodec_close(AVCodecContext* avctx)\r
+{\r
+       thread_free(avctx);\r
+       // ff_thread_free will not be executed since thread_opaque == nullptr.\r
+       return avcodec_close(avctx); \r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/tbb_avcodec.h b/modules/ffmpeg/producer/tbb_avcodec.h
new file mode 100644 (file)
index 0000000..2756cad
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+struct AVCodecContext;\r
+struct AVCodec;\r
+\r
+namespace caspar {\r
+       \r
+int tbb_avcodec_open(AVCodecContext *avctx, AVCodec *codec);\r
+int tbb_avcodec_close(AVCodecContext *avctx);\r
+\r
+}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/util/flv.cpp b/modules/ffmpeg/producer/util/flv.cpp
new file mode 100644 (file)
index 0000000..4b90631
--- /dev/null
@@ -0,0 +1,102 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "flv.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <boost/filesystem.hpp>\r
+\r
+#include <iostream>\r
+\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+std::map<std::string, std::string> read_flv_meta_info(const std::string& filename)\r
+{\r
+       std::map<std::string, std::string>  values;\r
+\r
+       if(boost::filesystem2::path(filename).extension() != ".flv")\r
+               return values;\r
+       \r
+       try\r
+       {\r
+               if(!boost::filesystem2::exists(filename))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception());\r
+       \r
+               std::fstream fileStream = std::fstream(filename, std::fstream::in);\r
+               \r
+               std::vector<char> bytes2(256);\r
+               fileStream.read(bytes2.data(), bytes2.size());\r
+\r
+               auto ptr = bytes2.data();\r
+               \r
+               ptr += 27;\r
+                                               \r
+               if(std::string(ptr, ptr+10) == "onMetaData")\r
+               {\r
+                       ptr += 16;\r
+\r
+                       for(int n = 0; n < 16; ++n)\r
+                       {\r
+                               char name_size = *ptr++;\r
+\r
+                               if(name_size == 0)\r
+                                       break;\r
+\r
+                               auto name = std::string(ptr, ptr + name_size);\r
+                               ptr += name_size;\r
+\r
+                               char data_type = *ptr++;\r
+                               switch(data_type)\r
+                               {\r
+                               case 0: // double\r
+                                       {\r
+                                               static_assert(sizeof(double) == 8, "");\r
+                                               std::reverse(ptr, ptr+8);\r
+                                               values[name] = boost::lexical_cast<std::string>(*(double*)(ptr));\r
+                                               ptr += 9;\r
+\r
+                                               break;\r
+                                       }\r
+                               case 1: // bool\r
+                                       {\r
+                                               values[name] = boost::lexical_cast<std::string>(*ptr != 0);\r
+                                               ptr += 2;\r
+\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+       }\r
+\r
+    return values;\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/util/flv.h b/modules/ffmpeg/producer/util/flv.h
new file mode 100644 (file)
index 0000000..6de0ba3
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+std::map<std::string, std::string> read_flv_meta_info(const std::string& filename);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/util/util.cpp b/modules/ffmpeg/producer/util/util.cpp
new file mode 100644 (file)
index 0000000..ceaa839
--- /dev/null
@@ -0,0 +1,537 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "util.h"\r
+\r
+#include "flv.h"\r
+\r
+#include "../tbb_avcodec.h"\r
+#include "../../ffmpeg_error.h"\r
+\r
+#include <tbb/concurrent_unordered_map.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame_producer.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/assert.h>\r
+#include <common/memory/memcpy.h>\r
+\r
+#include <tbb/parallel_for.h>\r
+\r
+#include <boost/filesystem.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libswscale/swscale.h>\r
+       #include <libavcodec/avcodec.h>\r
+       #include <libavformat/avformat.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar { namespace ffmpeg {\r
+               \r
+std::shared_ptr<core::audio_buffer> flush_audio()\r
+{\r
+       static std::shared_ptr<core::audio_buffer> audio(new core::audio_buffer());\r
+       return audio;\r
+}\r
+\r
+std::shared_ptr<core::audio_buffer> empty_audio()\r
+{\r
+       static std::shared_ptr<core::audio_buffer> audio(new core::audio_buffer());\r
+       return audio;\r
+}\r
+\r
+std::shared_ptr<AVFrame>                       flush_video()\r
+{\r
+       static std::shared_ptr<AVFrame> video(avcodec_alloc_frame(), av_free);\r
+       return video;\r
+}\r
+\r
+std::shared_ptr<AVFrame>                       empty_video()\r
+{\r
+       static std::shared_ptr<AVFrame> video(avcodec_alloc_frame(), av_free);\r
+       return video;\r
+}\r
+\r
+core::field_mode::type get_mode(const AVFrame& frame)\r
+{\r
+       if(!frame.interlaced_frame)\r
+               return core::field_mode::progressive;\r
+\r
+       return frame.top_field_first ? core::field_mode::upper : core::field_mode::lower;\r
+}\r
+\r
+core::pixel_format::type get_pixel_format(PixelFormat pix_fmt)\r
+{\r
+       switch(pix_fmt)\r
+       {\r
+       case CASPAR_PIX_FMT_LUMA:       return core::pixel_format::luma;\r
+       case PIX_FMT_GRAY8:                     return core::pixel_format::gray;\r
+       case PIX_FMT_BGRA:                      return core::pixel_format::bgra;\r
+       case PIX_FMT_ARGB:                      return core::pixel_format::argb;\r
+       case PIX_FMT_RGBA:                      return core::pixel_format::rgba;\r
+       case PIX_FMT_ABGR:                      return core::pixel_format::abgr;\r
+       case PIX_FMT_YUV444P:           return core::pixel_format::ycbcr;\r
+       case PIX_FMT_YUV422P:           return core::pixel_format::ycbcr;\r
+       case PIX_FMT_YUV420P:           return core::pixel_format::ycbcr;\r
+       case PIX_FMT_YUV411P:           return core::pixel_format::ycbcr;\r
+       case PIX_FMT_YUV410P:           return core::pixel_format::ycbcr;\r
+       case PIX_FMT_YUVA420P:          return core::pixel_format::ycbcra;\r
+       default:                                        return core::pixel_format::invalid;\r
+       }\r
+}\r
+\r
+core::pixel_format_desc get_pixel_format_desc(PixelFormat pix_fmt, size_t width, size_t height)\r
+{\r
+       // Get linesizes\r
+       AVPicture dummy_pict;   \r
+       avpicture_fill(&dummy_pict, nullptr, pix_fmt == CASPAR_PIX_FMT_LUMA ? PIX_FMT_GRAY8 : pix_fmt, width, height);\r
+\r
+       core::pixel_format_desc desc;\r
+       desc.pix_fmt = get_pixel_format(pix_fmt);\r
+               \r
+       switch(desc.pix_fmt)\r
+       {\r
+       case core::pixel_format::gray:\r
+       case core::pixel_format::luma:\r
+               {\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0], height, 1));                                               \r
+                       return desc;\r
+               }\r
+       case core::pixel_format::bgra:\r
+       case core::pixel_format::argb:\r
+       case core::pixel_format::rgba:\r
+       case core::pixel_format::abgr:\r
+               {\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0]/4, height, 4));                                             \r
+                       return desc;\r
+               }\r
+       case core::pixel_format::ycbcr:\r
+       case core::pixel_format::ycbcra:\r
+               {               \r
+                       // Find chroma height\r
+                       size_t size2 = dummy_pict.data[2] - dummy_pict.data[1];\r
+                       size_t h2 = size2/dummy_pict.linesize[1];                       \r
+\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0], height, 1));\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[1], h2, 1));\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[2], h2, 1));\r
+\r
+                       if(desc.pix_fmt == core::pixel_format::ycbcra)                                          \r
+                               desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[3], height, 1));       \r
+                       return desc;\r
+               }               \r
+       default:                \r
+               desc.pix_fmt = core::pixel_format::invalid;\r
+               return desc;\r
+       }\r
+}\r
+\r
+int make_alpha_format(int format)\r
+{\r
+       switch(get_pixel_format(static_cast<PixelFormat>(format)))\r
+       {\r
+       case core::pixel_format::ycbcr:\r
+       case core::pixel_format::ycbcra:\r
+               return CASPAR_PIX_FMT_LUMA;\r
+       default:\r
+               return format;\r
+       }\r
+}\r
+\r
+safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int hints)\r
+{                      \r
+       static tbb::concurrent_unordered_map<int64_t, tbb::concurrent_queue<std::shared_ptr<SwsContext>>> sws_contexts_;\r
+       \r
+       if(decoded_frame->width < 1 || decoded_frame->height < 1)\r
+               return make_safe<core::write_frame>(tag);\r
+\r
+       const auto width  = decoded_frame->width;\r
+       const auto height = decoded_frame->height;\r
+       auto desc                 = get_pixel_format_desc(static_cast<PixelFormat>(decoded_frame->format), width, height);\r
+       \r
+       if(hints & core::frame_producer::ALPHA_HINT)\r
+               desc = get_pixel_format_desc(static_cast<PixelFormat>(make_alpha_format(decoded_frame->format)), width, height);\r
+\r
+       std::shared_ptr<core::write_frame> write;\r
+\r
+       if(desc.pix_fmt == core::pixel_format::invalid)\r
+       {\r
+               auto pix_fmt = static_cast<PixelFormat>(decoded_frame->format);\r
+               auto target_pix_fmt = PIX_FMT_BGRA;\r
+\r
+               if(pix_fmt == PIX_FMT_UYVY422)\r
+                       target_pix_fmt = PIX_FMT_YUV422P;\r
+               else if(pix_fmt == PIX_FMT_YUYV422)\r
+                       target_pix_fmt = PIX_FMT_YUV422P;\r
+               else if(pix_fmt == PIX_FMT_UYYVYY411)\r
+                       target_pix_fmt = PIX_FMT_YUV411P;\r
+               else if(pix_fmt == PIX_FMT_YUV420P10)\r
+                       target_pix_fmt = PIX_FMT_YUV420P;\r
+               else if(pix_fmt == PIX_FMT_YUV422P10)\r
+                       target_pix_fmt = PIX_FMT_YUV422P;\r
+               else if(pix_fmt == PIX_FMT_YUV444P10)\r
+                       target_pix_fmt = PIX_FMT_YUV444P;\r
+               \r
+               auto target_desc = get_pixel_format_desc(target_pix_fmt, width, height);\r
+\r
+               write = frame_factory->create_frame(tag, target_desc);\r
+               write->set_type(get_mode(*decoded_frame));\r
+\r
+               std::shared_ptr<SwsContext> sws_context;\r
+\r
+               //CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
+               \r
+               int64_t key = ((static_cast<int64_t>(width)                      << 32) & 0xFFFF00000000) | \r
+                                         ((static_cast<int64_t>(height)                 << 16) & 0xFFFF0000) | \r
+                                         ((static_cast<int64_t>(pix_fmt)                <<  8) & 0xFF00) | \r
+                                         ((static_cast<int64_t>(target_pix_fmt) <<  0) & 0xFF);\r
+                       \r
+               auto& pool = sws_contexts_[key];\r
+                                               \r
+               if(!pool.try_pop(sws_context))\r
+               {\r
+                       double param;\r
+                       sws_context.reset(sws_getContext(width, height, pix_fmt, width, height, target_pix_fmt, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
+               }\r
+                       \r
+               if(!sws_context)\r
+               {\r
+                       BOOST_THROW_EXCEPTION(operation_failed() << msg_info("Could not create software scaling context.") << \r
+                                                                       boost::errinfo_api_function("sws_getContext"));\r
+               }       \r
+               \r
+               safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);     \r
+               avcodec_get_frame_defaults(av_frame.get());                     \r
+               if(target_pix_fmt == PIX_FMT_BGRA)\r
+               {\r
+                       auto size = avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), write->image_data().begin(), PIX_FMT_BGRA, width, height);\r
+                       CASPAR_VERIFY(size == write->image_data().size()); \r
+               }\r
+               else\r
+               {\r
+                       av_frame->width  = width;\r
+                       av_frame->height = height;\r
+                       for(size_t n = 0; n < target_desc.planes.size(); ++n)\r
+                       {\r
+                               av_frame->data[n]               = write->image_data(n).begin();\r
+                               av_frame->linesize[n]   = target_desc.planes[n].linesize;\r
+                       }\r
+               }\r
+\r
+               sws_scale(sws_context.get(), decoded_frame->data, decoded_frame->linesize, 0, height, av_frame->data, av_frame->linesize);      \r
+               pool.push(sws_context);\r
+\r
+               write->commit();                \r
+       }\r
+       else\r
+       {\r
+               write = frame_factory->create_frame(tag, desc);\r
+               write->set_type(get_mode(*decoded_frame));\r
+\r
+               for(int n = 0; n < static_cast<int>(desc.planes.size()); ++n)\r
+               {\r
+                       auto plane            = desc.planes[n];\r
+                       auto result           = write->image_data(n).begin();\r
+                       auto decoded          = decoded_frame->data[n];\r
+                       auto decoded_linesize = decoded_frame->linesize[n];\r
+                       \r
+                       CASPAR_ASSERT(decoded);\r
+                       CASPAR_ASSERT(write->image_data(n).begin());\r
+\r
+                       if(decoded_linesize != static_cast<int>(plane.width))\r
+                       {\r
+                               // Copy line by line since ffmpeg sometimes pads each line.\r
+                               tbb::parallel_for<size_t>(0, desc.planes[n].height, [&](size_t y)\r
+                               {\r
+                                       fast_memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
+                               });\r
+                       }\r
+                       else\r
+                       {\r
+                               fast_memcpy(result, decoded, plane.size);\r
+                       }\r
+\r
+                       write->commit(n);\r
+               }\r
+       }\r
+\r
+       if(decoded_frame->height == 480) // NTSC DV\r
+       {\r
+               write->get_frame_transform().fill_translation[1] += 2.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
+               write->get_frame_transform().fill_scale[1] = 1.0 - 6.0*1.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
+       }\r
+       \r
+       // Fix field-order if needed\r
+       if(write->get_type() == core::field_mode::lower && frame_factory->get_video_format_desc().field_mode == core::field_mode::upper)\r
+               write->get_frame_transform().fill_translation[1] += 1.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
+       else if(write->get_type() == core::field_mode::upper && frame_factory->get_video_format_desc().field_mode == core::field_mode::lower)\r
+               write->get_frame_transform().fill_translation[1] -= 1.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
+\r
+       return make_safe_ptr(write);\r
+}\r
+\r
+bool is_sane_fps(AVRational time_base)\r
+{\r
+       double fps = static_cast<double>(time_base.den) / static_cast<double>(time_base.num);\r
+       return fps > 20.0 && fps < 65.0;\r
+}\r
+\r
+AVRational fix_time_base(AVRational time_base)\r
+{\r
+       if(time_base.num == 1)\r
+               time_base.num = static_cast<int>(std::pow(10.0, static_cast<int>(std::log10(static_cast<float>(time_base.den)))-1));    \r
+                       \r
+       if(!is_sane_fps(time_base))\r
+       {\r
+               auto tmp = time_base;\r
+               tmp.den /= 2;\r
+               if(is_sane_fps(tmp))\r
+                       time_base = tmp;\r
+       }\r
+\r
+       return time_base;\r
+}\r
+\r
+double read_fps(AVFormatContext& context, double fail_value)\r
+{                                              \r
+       auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
+       auto audio_index = av_find_best_stream(&context, AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0);\r
+       \r
+       if(video_index > -1)\r
+       {\r
+               const auto video_context = context.streams[video_index]->codec;\r
+               const auto video_stream  = context.streams[video_index];\r
+                                               \r
+               AVRational time_base = video_context->time_base;\r
+\r
+               if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
+               {\r
+                       try\r
+                       {\r
+                               auto meta = read_flv_meta_info(context.filename);\r
+                               return boost::lexical_cast<double>(meta["framerate"]);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               return 0.0;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       time_base.num *= video_context->ticks_per_frame;\r
+\r
+                       if(!is_sane_fps(time_base))\r
+                       {                       \r
+                               time_base = fix_time_base(time_base);\r
+\r
+                               if(!is_sane_fps(time_base) && audio_index > -1)\r
+                               {\r
+                                       auto& audio_context = *context.streams[audio_index]->codec;\r
+                                       auto& audio_stream  = *context.streams[audio_index];\r
+\r
+                                       double duration_sec = audio_stream.duration / static_cast<double>(audio_context.sample_rate);\r
+                                                               \r
+                                       time_base.num = static_cast<int>(duration_sec*100000.0);\r
+                                       time_base.den = static_cast<int>(video_stream->nb_frames*100000);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               double fps = static_cast<double>(time_base.den) / static_cast<double>(time_base.num);\r
+\r
+               double closest_fps = 0.0;\r
+               for(int n = 0; n < core::video_format::count; ++n)\r
+               {\r
+                       auto format = core::video_format_desc::get(static_cast<core::video_format::type>(n));\r
+\r
+                       double diff1 = std::abs(format.fps - fps);\r
+                       double diff2 = std::abs(closest_fps - fps);\r
+\r
+                       if(diff1 < diff2)\r
+                               closest_fps = format.fps;\r
+               }\r
+       \r
+               return closest_fps;\r
+       }\r
+\r
+       return fail_value;      \r
+}\r
+\r
+void fix_meta_data(AVFormatContext& context)\r
+{\r
+       auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
+\r
+       if(video_index > -1)\r
+       {\r
+               auto video_stream   = context.streams[video_index];\r
+               auto video_context  = context.streams[video_index]->codec;\r
+                                               \r
+               if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
+               {\r
+                       try\r
+                       {\r
+                               auto meta = read_flv_meta_info(context.filename);\r
+                               double fps = boost::lexical_cast<double>(meta["framerate"]);\r
+                               video_stream->nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
+                       }\r
+                       catch(...){}\r
+               }\r
+               else\r
+               {\r
+                       auto stream_time = video_stream->time_base;\r
+                       auto duration    = video_stream->duration;\r
+                       auto codec_time  = video_context->time_base;\r
+                       auto ticks               = video_context->ticks_per_frame;\r
+\r
+                       if(video_stream->nb_frames == 0)\r
+                               video_stream->nb_frames = (duration*stream_time.num*codec_time.den)/(stream_time.den*codec_time.num*ticks);     \r
+               }\r
+       }\r
+}\r
+\r
+safe_ptr<AVPacket> create_packet()\r
+{\r
+       safe_ptr<AVPacket> packet(new AVPacket, [](AVPacket* p)\r
+       {\r
+               av_free_packet(p);\r
+               delete p;\r
+       });\r
+       \r
+       av_init_packet(packet.get());\r
+       return packet;\r
+}\r
+\r
+safe_ptr<AVCodecContext> open_codec(AVFormatContext& context, enum AVMediaType type, int& index)\r
+{      \r
+       AVCodec* decoder;\r
+       index = THROW_ON_ERROR2(av_find_best_stream(&context, type, -1, -1, &decoder, 0), "");\r
+       //if(strcmp(decoder->name, "prores") == 0 && decoder->next && strcmp(decoder->next->name, "prores_lgpl") == 0)\r
+       //      decoder = decoder->next;\r
+\r
+       THROW_ON_ERROR2(tbb_avcodec_open(context.streams[index]->codec, decoder), "");\r
+       return safe_ptr<AVCodecContext>(context.streams[index]->codec, tbb_avcodec_close);\r
+}\r
+\r
+safe_ptr<AVFormatContext> open_input(const std::wstring& filename)\r
+{\r
+       AVFormatContext* weak_context = nullptr;\r
+       THROW_ON_ERROR2(avformat_open_input(&weak_context, narrow(filename).c_str(), nullptr, nullptr), filename);\r
+       safe_ptr<AVFormatContext> context(weak_context, av_close_input_file);                   \r
+       THROW_ON_ERROR2(avformat_find_stream_info(weak_context, nullptr), filename);\r
+       fix_meta_data(*context);\r
+       return context;\r
+}\r
+\r
+std::wstring print_mode(size_t width, size_t height, double fps, bool interlaced)\r
+{\r
+       std::wostringstream fps_ss;\r
+       fps_ss << std::fixed << std::setprecision(2) << (!interlaced ? fps : 2.0 * fps);\r
+\r
+       return boost::lexical_cast<std::wstring>(width) + L"x" + boost::lexical_cast<std::wstring>(height) + (!interlaced ? L"p" : L"i") + fps_ss.str();\r
+}\r
+\r
+bool is_valid_file(const std::wstring filename, const std::vector<std::wstring>& invalid_exts)\r
+{\r
+       static std::vector<std::wstring> valid_exts = boost::assign::list_of(L".m2t")(L".mov")(L".mp4")(L".dv")(L".flv")(L".mpg")(L".wav")(L".mp3")(L".dnxhd")(L".h264")(L".prores");\r
+\r
+       auto ext = boost::to_lower_copy(boost::filesystem::wpath(filename).extension());\r
+               \r
+       if(std::find(invalid_exts.begin(), invalid_exts.end(), ext) != invalid_exts.end())\r
+               return false;   \r
+\r
+       if(std::find(valid_exts.begin(), valid_exts.end(), ext) != valid_exts.end())\r
+               return true;    \r
+\r
+       auto filename2 = narrow(filename);\r
+\r
+       if(boost::filesystem::path(filename2).extension() == ".m2t")\r
+               return true;\r
+\r
+       std::ifstream file(filename);\r
+\r
+       std::vector<unsigned char> buf;\r
+       for(auto file_it = std::istreambuf_iterator<char>(file); file_it != std::istreambuf_iterator<char>() && buf.size() < 2048; ++file_it)\r
+               buf.push_back(*file_it);\r
+\r
+       if(buf.empty())\r
+               return nullptr;\r
+\r
+       AVProbeData pb;\r
+       pb.filename = filename2.c_str();\r
+       pb.buf          = buf.data();\r
+       pb.buf_size = buf.size();\r
+\r
+       int score = 0;\r
+       return av_probe_input_format2(&pb, true, &score) != nullptr;\r
+}\r
+\r
+bool is_valid_file(const std::wstring filename)\r
+{\r
+       static const std::vector<std::wstring> invalid_exts = boost::assign::list_of(L".png")(L".tga")(L".bmp")(L".jpg")(L".jpeg")(L".gif")(L".tiff")(L".tif")(L".jp2")(L".jpx")(L".j2k")(L".j2c")(L".swf")(L".ct");\r
+       \r
+       return is_valid_file(filename, invalid_exts);\r
+}\r
+\r
+std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts)\r
+{\r
+       auto stem2 = boost::filesystem2::wpath(stem);\r
+       auto dir = stem2.parent_path();\r
+       for(auto it = boost::filesystem2::wdirectory_iterator(dir); it != boost::filesystem2::wdirectory_iterator(); ++it)\r
+       {\r
+               if(boost::iequals(it->path().stem(), stem2.filename()) && is_valid_file(it->path().file_string(), invalid_exts))\r
+                       return it->path().file_string();\r
+       }\r
+       return L"";\r
+}\r
+//\r
+//void av_dup_frame(AVFrame* frame)\r
+//{\r
+//     AVFrame* new_frame = avcodec_alloc_frame();\r
+//\r
+//\r
+//     const uint8_t *src_data[4] = {0};\r
+//     memcpy(const_cast<uint8_t**>(&src_data[0]), frame->data, 4);\r
+//     const int src_linesizes[4] = {0};\r
+//     memcpy(const_cast<int*>(&src_linesizes[0]), frame->linesize, 4);\r
+//\r
+//     av_image_alloc(new_frame->data, new_frame->linesize, new_frame->width, new_frame->height, frame->format, 16);\r
+//\r
+//     av_image_copy(new_frame->data, new_frame->linesize, src_data, src_linesizes, frame->format, new_frame->width, new_frame->height);\r
+//\r
+//     frame =\r
+//}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/util/util.h b/modules/ffmpeg/producer/util/util.h
new file mode 100644 (file)
index 0000000..c830427
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/video_format.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/mixer/audio/audio_mixer.h>\r
+\r
+enum PixelFormat;\r
+struct AVFrame;\r
+struct AVFormatContext;\r
+struct AVPacket;\r
+struct AVRational;\r
+struct AVCodecContext;\r
+\r
+namespace caspar {\r
+\r
+namespace core {\r
+\r
+struct pixel_format_desc;\r
+class write_frame;\r
+struct frame_factory;\r
+\r
+}\r
+\r
+namespace ffmpeg {\r
+               \r
+std::shared_ptr<core::audio_buffer> flush_audio();\r
+std::shared_ptr<core::audio_buffer> empty_audio();\r
+std::shared_ptr<AVFrame>                       flush_video();\r
+std::shared_ptr<AVFrame>                       empty_video();\r
+\r
+// Utils\r
+\r
+static const int CASPAR_PIX_FMT_LUMA = 10; // Just hijack some unual pixel format.\r
+\r
+core::field_mode::type         get_mode(const AVFrame& frame);\r
+int                                                    make_alpha_format(int format); // NOTE: Be careful about CASPAR_PIX_FMT_LUMA, change it to PIX_FMT_GRAY8 if you want to use the frame inside some ffmpeg function.\r
+safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int hints);\r
+\r
+safe_ptr<AVPacket> create_packet();\r
+\r
+safe_ptr<AVCodecContext> open_codec(AVFormatContext& context,  enum AVMediaType type, int& index);\r
+safe_ptr<AVFormatContext> open_input(const std::wstring& filename);\r
+\r
+bool is_sane_fps(AVRational time_base);\r
+AVRational fix_time_base(AVRational time_base);\r
+\r
+double read_fps(AVFormatContext& context, double fail_value);\r
+\r
+std::wstring print_mode(size_t width, size_t height, double fps, bool interlaced);\r
+\r
+std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts);\r
+bool is_valid_file(const std::wstring filename, const std::vector<std::wstring>& invalid_exts);\r
+bool is_valid_file(const std::wstring filename);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/video/video_decoder.cpp b/modules/ffmpeg/producer/video/video_decoder.cpp
new file mode 100644 (file)
index 0000000..416f3d3
--- /dev/null
@@ -0,0 +1,164 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "video_decoder.h"\r
+\r
+#include "../util/util.h"\r
+\r
+#include "../../ffmpeg_error.h"\r
+\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+\r
+#include <boost/range/algorithm_ext/push_back.hpp>\r
+#include <boost/filesystem.hpp>\r
+\r
+#include <queue>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #include <libavcodec/avcodec.h>\r
+       #include <libavformat/avformat.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+namespace caspar { namespace ffmpeg {\r
+       \r
+struct video_decoder::implementation : boost::noncopyable\r
+{\r
+       int                                                                             index_;\r
+       const safe_ptr<AVCodecContext>                  codec_context_;\r
+\r
+       std::queue<safe_ptr<AVPacket>>                  packets_;\r
+       \r
+       const uint32_t                                                  nb_frames_;\r
+\r
+       const size_t                                                    width_;\r
+       const size_t                                                    height_;\r
+       bool                                                                    is_progressive_;\r
+\r
+       tbb::atomic<size_t>                                             file_frame_number_;\r
+\r
+public:\r
+       explicit implementation(const safe_ptr<AVFormatContext>& context) \r
+               : codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_))\r
+               , nb_frames_(static_cast<uint32_t>(context->streams[index_]->nb_frames))\r
+               , width_(codec_context_->width)\r
+               , height_(codec_context_->height)\r
+       {\r
+               file_frame_number_ = 0;\r
+       }\r
+\r
+       void push(const std::shared_ptr<AVPacket>& packet)\r
+       {\r
+               if(!packet)\r
+                       return;\r
+\r
+               if(packet->stream_index == index_ || packet->data == nullptr)\r
+                       packets_.push(make_safe_ptr(packet));\r
+       }\r
+\r
+       std::shared_ptr<AVFrame> poll()\r
+       {               \r
+               if(packets_.empty())\r
+                       return nullptr;\r
+               \r
+               auto packet = packets_.front();\r
+                                       \r
+               if(packet->data == nullptr)\r
+               {                       \r
+                       if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
+                       {\r
+                               auto video = decode(*packet);\r
+                               if(video)\r
+                                       return video;\r
+                       }\r
+                                       \r
+                       packets_.pop();\r
+                       file_frame_number_ = static_cast<size_t>(packet->pos);\r
+                       avcodec_flush_buffers(codec_context_.get());\r
+                       return flush_video();   \r
+               }\r
+                       \r
+               packets_.pop();\r
+               return decode(*packet);\r
+       }\r
+\r
+       std::shared_ptr<AVFrame> decode(AVPacket& pkt)\r
+       {\r
+               std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
+\r
+               int frame_finished = 0;\r
+               THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &pkt), "[video_decocer]");\r
+               \r
+               // If a decoder consumes less then the whole packet then something is wrong\r
+               // that might be just harmless padding at the end, or a problem with the\r
+               // AVParser or demuxer which puted more then one frame in a AVPacket.\r
+\r
+               if(frame_finished == 0) \r
+                       return nullptr;\r
+\r
+               is_progressive_ = !decoded_frame->interlaced_frame;\r
+\r
+               if(decoded_frame->repeat_pict > 0)\r
+                       CASPAR_LOG(warning) << "[video_decoder] Field repeat_pict not implemented.";\r
+               \r
+               ++file_frame_number_;\r
+\r
+               return decoded_frame;\r
+       }\r
+       \r
+       bool ready() const\r
+       {\r
+               return packets_.size() >= 8;\r
+       }\r
+\r
+       uint32_t nb_frames() const\r
+       {\r
+               return std::max<uint32_t>(nb_frames_, file_frame_number_);\r
+       }\r
+\r
+       std::wstring print() const\r
+       {               \r
+               return L"[video-decoder] " + widen(codec_context_->codec->long_name);\r
+       }\r
+};\r
+\r
+video_decoder::video_decoder(const safe_ptr<AVFormatContext>& context) : impl_(new implementation(context)){}\r
+void video_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
+std::shared_ptr<AVFrame> video_decoder::poll(){return impl_->poll();}\r
+bool video_decoder::ready() const{return impl_->ready();}\r
+size_t video_decoder::width() const{return impl_->width_;}\r
+size_t video_decoder::height() const{return impl_->height_;}\r
+uint32_t video_decoder::nb_frames() const{return impl_->nb_frames();}\r
+uint32_t video_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
+bool   video_decoder::is_progressive() const{return impl_->is_progressive_;}\r
+std::wstring video_decoder::print() const{return impl_->print();}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/video/video_decoder.h b/modules/ffmpeg/producer/video/video_decoder.h
new file mode 100644 (file)
index 0000000..d84ae6a
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+struct AVFormatContext;\r
+struct AVFrame;\r
+struct AVPacket;\r
+\r
+namespace caspar {\r
+\r
+namespace core {\r
+       struct frame_factory;\r
+       class write_frame;\r
+}\r
+\r
+namespace ffmpeg {\r
+\r
+class video_decoder : boost::noncopyable\r
+{\r
+public:\r
+       explicit video_decoder(const safe_ptr<AVFormatContext>& context);\r
+       \r
+       bool ready() const;\r
+       void push(const std::shared_ptr<AVPacket>& packet);\r
+       std::shared_ptr<AVFrame> poll();\r
+       \r
+       size_t   width()                const;\r
+       size_t   height()       const;\r
+\r
+       uint32_t nb_frames() const;\r
+       uint32_t file_frame_number() const;\r
+\r
+       bool     is_progressive() const;\r
+\r
+       std::wstring print() const;\r
+\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/StdAfx.cpp b/modules/flash/StdAfx.cpp
new file mode 100644 (file)
index 0000000..f2b946a
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "stdafx.h"
\ No newline at end of file
diff --git a/modules/flash/StdAfx.h b/modules/flash/StdAfx.h
new file mode 100644 (file)
index 0000000..66089eb
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../common/compiler/vs/disable_silly_warnings.h"\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#include <assert.h>\r
+#include <memory>\r
+#include <array>\r
+#include <functional>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <deque>\r
+#include <queue>\r
+#include <string>\r
+#include <math.h>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/format.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/regex.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include "../common/utility/string.h"\r
+#include "../common/memory/safe_ptr.h"\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include "../common/log/Log.h"\r
+#include "../common/exception/exceptions.h"\r
+#include "../common/exception/win32_exception.h"\r
diff --git a/modules/flash/flash.cpp b/modules/flash/flash.cpp
new file mode 100644 (file)
index 0000000..40a1cc2
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "flash.h"\r
+\r
+#include "producer/cg_producer.h"\r
+#include "producer/flash_producer.h"\r
+\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/env.h>\r
+\r
+#include <boost/regex.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace flash {\r
+\r
+void init()\r
+{\r
+       core::register_producer_factory(create_ct_producer);\r
+       core::register_producer_factory(create_cg_producer);\r
+       core::register_producer_factory(create_swf_producer);\r
+}\r
+\r
+std::wstring get_cg_version()\r
+{\r
+       try\r
+       {\r
+               struct dummy_factory : public core::frame_factory\r
+               {\r
+               \r
+                       virtual safe_ptr<core::write_frame> create_frame(const void* video_stream_tag, const core::pixel_format_desc& desc) \r
+                       {\r
+                               return make_safe<core::write_frame>(nullptr);\r
+                       }\r
+       \r
+                       virtual core::video_format_desc get_video_format_desc() const\r
+                       {\r
+                               return core::video_format_desc::get(L"PAL");\r
+                       }\r
+               };\r
+\r
+               std::vector<std::wstring> params;\r
+               auto producer = make_safe<cg_producer>(flash::create_producer(make_safe<dummy_factory>(), params));\r
+\r
+               auto info = producer->template_host_info();\r
+       \r
+               boost::wregex ver_exp(L"version=&quot;(?<VERSION>[^&]*)");\r
+               boost::wsmatch what;\r
+               if(boost::regex_search(info, what, ver_exp))\r
+                       return what[L"VERSION"];\r
+       }\r
+       catch(...)\r
+       {\r
+\r
+       }\r
+\r
+       return L"Unknown";\r
+}\r
+\r
+std::wstring get_version()\r
+{              \r
+       std::wstring version = L"Not found";\r
+#ifdef WIN32\r
+       HKEY   hkey;\r
\r
+       DWORD dwType, dwSize;\r
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Macromedia\\FlashPlayerActiveX"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
+       {\r
+               wchar_t ver_str[1024];\r
+\r
+               dwType = REG_SZ;\r
+               dwSize = sizeof(ver_str);\r
+               RegQueryValueEx(hkey, TEXT("Version"), NULL, &dwType, (PBYTE)&ver_str, &dwSize);\r
\r
+               version = ver_str;\r
+\r
+               RegCloseKey(hkey);\r
+       }\r
+#endif\r
+       return version;\r
+}\r
+\r
+}}\r
diff --git a/modules/flash/flash.h b/modules/flash/flash.h
new file mode 100644 (file)
index 0000000..bda6402
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace flash {\r
+\r
+void init();\r
+\r
+std::wstring get_cg_version();\r
+std::wstring get_version();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/flash.vcxproj b/modules/flash/flash.vcxproj
new file mode 100644 (file)
index 0000000..1b8bdb8
--- /dev/null
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{816DEABA-3757-4306-AFE0-C27CF96C4DEA}</ProjectGuid>\r
+    <RootNamespace>flash</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>flash</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\zlib\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\zlib\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\zlib\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\zlib\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\Flash9e.IDL">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </Midl>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="flash.cpp" />\r
+    <ClCompile Include="interop\Flash9e_i.c">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\cg_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\FlashAxContainer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\flash_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="util\swf.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="flash.h" />\r
+    <ClInclude Include="interop\axflash.h" />\r
+    <ClInclude Include="interop\TimerHelper.h" />\r
+    <ClInclude Include="producer\cg_producer.h" />\r
+    <ClInclude Include="producer\FlashAxContainer.h" />\r
+    <ClInclude Include="producer\flash_producer.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\swf.h" />\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/flash/flash.vcxproj.filters b/modules/flash/flash.vcxproj.filters
new file mode 100644 (file)
index 0000000..4d5c878
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{38d97478-b199-48b5-a3ad-b930146d752f}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{448da3f4-8d88-4c18-856b-8f8ecc190d1e}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\interop">\r
+      <UniqueIdentifier>{bd73f842-a8f5-4d98-92cf-81c623283dde}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\util">\r
+      <UniqueIdentifier>{74e59dfb-eba8-4169-ae40-4b6ac7bcbe3d}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\Flash9e.IDL">\r
+      <Filter>source\interop</Filter>\r
+    </Midl>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="interop\Flash9e_i.c">\r
+      <Filter>source\interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\flash_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\FlashAxContainer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\cg_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="flash.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\swf.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="interop\TimerHelper.h">\r
+      <Filter>source\interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\axflash.h">\r
+      <Filter>source\interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\cg_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\flash_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\FlashAxContainer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="flash.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\swf.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/flash/interop/Flash9e.IDL b/modules/flash/interop/Flash9e.IDL
new file mode 100644 (file)
index 0000000..c85a3bb
--- /dev/null
@@ -0,0 +1,367 @@
+// Generated .IDL file (by the OLE/COM Object Viewer)\r
+// \r
+// typelib filename: Flash9e.ocx\r
+\r
+[\r
+  uuid(D27CDB6B-AE6D-11CF-96B8-444553540000),\r
+  version(1.0),\r
+  helpstring("Shockwave Flash"),\r
+  custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663662),\r
+  custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1180654890)\r
+\r
+]\r
+library ShockwaveFlashObjects\r
+{\r
+    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}\r
+    importlib("stdole2.tlb");\r
+\r
+    // Forward declare all types defined in this typelib\r
+    interface IShockwaveFlash;\r
+    dispinterface _IShockwaveFlashEvents;\r
+    interface IFlashFactory;\r
+    interface IFlashObjectInterface;\r
+    interface IDispatchEx;\r
+    interface IServiceProvider;\r
+\r
+    [\r
+      odl,\r
+      uuid(D27CDB6C-AE6D-11CF-96B8-444553540000),\r
+      helpstring("Shockwave Flash"),\r
+      dual,\r
+      oleautomation\r
+    ]\r
+    interface IShockwaveFlash : IDispatch {\r
+        [id(0xfffffdf3), propget, helpstring("property ReadyState")]\r
+        HRESULT ReadyState([out, retval] long* pVal);\r
+        [id(0x0000007c), propget, helpstring("property TotalFrames")]\r
+        HRESULT TotalFrames([out, retval] long* pVal);\r
+        [id(0x0000007d), propget, helpstring("property Playing")]\r
+        HRESULT Playing([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x0000007d), propput, helpstring("property Playing")]\r
+        HRESULT Playing([in] VARIANT_BOOL pVal);\r
+        [id(0x00000069), propget, helpstring("property Quality")]\r
+        HRESULT Quality([out, retval] int* pVal);\r
+        [id(0x00000069), propput, helpstring("property Quality")]\r
+        HRESULT Quality([in] int pVal);\r
+        [id(0x00000078), propget, helpstring("property ScaleMode")]\r
+        HRESULT ScaleMode([out, retval] int* pVal);\r
+        [id(0x00000078), propput, helpstring("property ScaleMode")]\r
+        HRESULT ScaleMode([in] int pVal);\r
+        [id(0x00000079), propget, helpstring("property AlignMode")]\r
+        HRESULT AlignMode([out, retval] int* pVal);\r
+        [id(0x00000079), propput, helpstring("property AlignMode")]\r
+        HRESULT AlignMode([in] int pVal);\r
+        [id(0x0000007b), propget, helpstring("property BackgroundColor")]\r
+        HRESULT BackgroundColor([out, retval] long* pVal);\r
+        [id(0x0000007b), propput, helpstring("property BackgroundColor")]\r
+        HRESULT BackgroundColor([in] long pVal);\r
+        [id(0x0000006a), propget, helpstring("property Loop")]\r
+        HRESULT Loop([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x0000006a), propput, helpstring("property Loop")]\r
+        HRESULT Loop([in] VARIANT_BOOL pVal);\r
+        [id(0x00000066), propget, helpstring("property Movie")]\r
+        HRESULT Movie([out, retval] BSTR* pVal);\r
+        [id(0x00000066), propput, helpstring("property Movie")]\r
+        HRESULT Movie([in] BSTR pVal);\r
+        [id(0x0000006b), propget, helpstring("property FrameNum")]\r
+        HRESULT FrameNum([out, retval] long* pVal);\r
+        [id(0x0000006b), propput, helpstring("property FrameNum")]\r
+        HRESULT FrameNum([in] long pVal);\r
+        [id(0x0000006d), helpstring("method SetZoomRect")]\r
+        HRESULT SetZoomRect(\r
+                        [in] long left, \r
+                        [in] long top, \r
+                        [in] long right, \r
+                        [in] long bottom);\r
+        [id(0x00000076), helpstring("method Zoom")]\r
+        HRESULT Zoom([in] int factor);\r
+        [id(0x00000077), helpstring("method Pan")]\r
+        HRESULT Pan(\r
+                        [in] long x, \r
+                        [in] long y, \r
+                        [in] int mode);\r
+        [id(0x00000070), helpstring("method Play")]\r
+        HRESULT Play();\r
+        [id(0x00000071), helpstring("method Stop")]\r
+        HRESULT Stop();\r
+        [id(0x00000072), helpstring("method Back")]\r
+        HRESULT Back();\r
+        [id(0x00000073), helpstring("method Forward")]\r
+        HRESULT Forward();\r
+        [id(0x00000074), helpstring("method Rewind")]\r
+        HRESULT Rewind();\r
+        [id(0x0000007e), helpstring("method StopPlay")]\r
+        HRESULT StopPlay();\r
+        [id(0x0000007f), helpstring("method GotoFrame")]\r
+        HRESULT GotoFrame([in] long FrameNum);\r
+        [id(0x00000080), helpstring("method CurrentFrame")]\r
+        HRESULT CurrentFrame([out, retval] long* FrameNum);\r
+        [id(0x00000081), helpstring("method IsPlaying")]\r
+        HRESULT IsPlaying([out, retval] VARIANT_BOOL* Playing);\r
+        [id(0x00000082), helpstring("method PercentLoaded")]\r
+        HRESULT PercentLoaded([out, retval] long* percent);\r
+        [id(0x00000083), helpstring("method FrameLoaded")]\r
+        HRESULT FrameLoaded(\r
+                        [in] long FrameNum, \r
+                        [out, retval] VARIANT_BOOL* loaded);\r
+        [id(0x00000084), helpstring("method FlashVersion")]\r
+        HRESULT FlashVersion([out, retval] long* version);\r
+        [id(0x00000085), propget, helpstring("property WMode")]\r
+        HRESULT WMode([out, retval] BSTR* pVal);\r
+        [id(0x00000085), propput, helpstring("property WMode")]\r
+        HRESULT WMode([in] BSTR pVal);\r
+        [id(0x00000086), propget, helpstring("property SAlign")]\r
+        HRESULT SAlign([out, retval] BSTR* pVal);\r
+        [id(0x00000086), propput, helpstring("property SAlign")]\r
+        HRESULT SAlign([in] BSTR pVal);\r
+        [id(0x00000087), propget, helpstring("property Menu")]\r
+        HRESULT Menu([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x00000087), propput, helpstring("property Menu")]\r
+        HRESULT Menu([in] VARIANT_BOOL pVal);\r
+        [id(0x00000088), propget, helpstring("property Base")]\r
+        HRESULT Base([out, retval] BSTR* pVal);\r
+        [id(0x00000088), propput, helpstring("property Base")]\r
+        HRESULT Base([in] BSTR pVal);\r
+        [id(0x00000089), propget, helpstring("property Scale")]\r
+        HRESULT Scale([out, retval] BSTR* pVal);\r
+        [id(0x00000089), propput, helpstring("property Scale")]\r
+        HRESULT Scale([in] BSTR pVal);\r
+        [id(0x0000008a), propget, helpstring("property DeviceFont")]\r
+        HRESULT DeviceFont([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x0000008a), propput, helpstring("property DeviceFont")]\r
+        HRESULT DeviceFont([in] VARIANT_BOOL pVal);\r
+        [id(0x0000008b), propget, helpstring("property EmbedMovie")]\r
+        HRESULT EmbedMovie([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x0000008b), propput, helpstring("property EmbedMovie")]\r
+        HRESULT EmbedMovie([in] VARIANT_BOOL pVal);\r
+        [id(0x0000008c), propget, helpstring("property BGColor")]\r
+        HRESULT BGColor([out, retval] BSTR* pVal);\r
+        [id(0x0000008c), propput, helpstring("property BGColor")]\r
+        HRESULT BGColor([in] BSTR pVal);\r
+        [id(0x0000008d), propget, helpstring("property Quality2")]\r
+        HRESULT Quality2([out, retval] BSTR* pVal);\r
+        [id(0x0000008d), propput, helpstring("property Quality2")]\r
+        HRESULT Quality2([in] BSTR pVal);\r
+        [id(0x0000008e), helpstring("method LoadMovie")]\r
+        HRESULT LoadMovie(\r
+                        [in] int layer, \r
+                        [in] BSTR url);\r
+        [id(0x0000008f), helpstring("method TGotoFrame")]\r
+        HRESULT TGotoFrame(\r
+                        [in] BSTR target, \r
+                        [in] long FrameNum);\r
+        [id(0x00000090), helpstring("method TGotoLabel")]\r
+        HRESULT TGotoLabel(\r
+                        [in] BSTR target, \r
+                        [in] BSTR label);\r
+        [id(0x00000091), helpstring("method TCurrentFrame")]\r
+        HRESULT TCurrentFrame(\r
+                        [in] BSTR target, \r
+                        [out, retval] long* FrameNum);\r
+        [id(0x00000092), helpstring("method TCurrentLabel")]\r
+        HRESULT TCurrentLabel(\r
+                        [in] BSTR target, \r
+                        [out, retval] BSTR* pVal);\r
+        [id(0x00000093), helpstring("method TPlay")]\r
+        HRESULT TPlay([in] BSTR target);\r
+        [id(0x00000094), helpstring("method TStopPlay")]\r
+        HRESULT TStopPlay([in] BSTR target);\r
+        [id(0x00000097), helpstring("method SetVariable")]\r
+        HRESULT SetVariable(\r
+                        [in] BSTR name, \r
+                        [in] BSTR value);\r
+        [id(0x00000098), helpstring("method GetVariable")]\r
+        HRESULT GetVariable(\r
+                        [in] BSTR name, \r
+                        [out, retval] BSTR* pVal);\r
+        [id(0x00000099), helpstring("method TSetProperty")]\r
+        HRESULT TSetProperty(\r
+                        [in] BSTR target, \r
+                        [in] int property, \r
+                        [in] BSTR value);\r
+        [id(0x0000009a), helpstring("method TGetProperty")]\r
+        HRESULT TGetProperty(\r
+                        [in] BSTR target, \r
+                        [in] int property, \r
+                        [out, retval] BSTR* pVal);\r
+        [id(0x0000009b), helpstring("method TCallFrame")]\r
+        HRESULT TCallFrame(\r
+                        [in] BSTR target, \r
+                        [in] int FrameNum);\r
+        [id(0x0000009c), helpstring("method TCallLabel")]\r
+        HRESULT TCallLabel(\r
+                        [in] BSTR target, \r
+                        [in] BSTR label);\r
+        [id(0x0000009d), helpstring("method TSetPropertyNum")]\r
+        HRESULT TSetPropertyNum(\r
+                        [in] BSTR target, \r
+                        [in] int property, \r
+                        [in] double value);\r
+        [id(0x0000009e), helpstring("method TGetPropertyNum")]\r
+        HRESULT TGetPropertyNum(\r
+                        [in] BSTR target, \r
+                        [in] int property, \r
+                        [out, retval] double* pVal);\r
+        [id(0x000000ac), helpstring("method TGetPropertyAsNumber")]\r
+        HRESULT TGetPropertyAsNumber(\r
+                        [in] BSTR target, \r
+                        [in] int property, \r
+                        [out, retval] double* pVal);\r
+        [id(0x0000009f), propget, helpstring("property SWRemote")]\r
+        HRESULT SWRemote([out, retval] BSTR* pVal);\r
+        [id(0x0000009f), propput, helpstring("property SWRemote")]\r
+        HRESULT SWRemote([in] BSTR pVal);\r
+        [id(0x000000aa), propget, helpstring("property FlashVars")]\r
+        HRESULT FlashVars([out, retval] BSTR* pVal);\r
+        [id(0x000000aa), propput, helpstring("property FlashVars")]\r
+        HRESULT FlashVars([in] BSTR pVal);\r
+        [id(0x000000ab), propget, helpstring("property AllowScriptAccess")]\r
+        HRESULT AllowScriptAccess([out, retval] BSTR* pVal);\r
+        [id(0x000000ab), propput, helpstring("property AllowScriptAccess")]\r
+        HRESULT AllowScriptAccess([in] BSTR pVal);\r
+        [id(0x000000be), propget, helpstring("property MovieData")]\r
+        HRESULT MovieData([out, retval] BSTR* pVal);\r
+        [id(0x000000be), propput, helpstring("property MovieData")]\r
+        HRESULT MovieData([in] BSTR pVal);\r
+        [id(0x000000bf), propget, helpstring("property inline-data")]\r
+        HRESULT InlineData([out, retval] IUnknown** ppIUnknown);\r
+        [id(0x000000bf), propput, helpstring("property inline-data")]\r
+        HRESULT InlineData([in] IUnknown* ppIUnknown);\r
+        [id(0x000000c0), propget, helpstring("property SeamlessTabbing")]\r
+        HRESULT SeamlessTabbing([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x000000c0), propput, helpstring("property SeamlessTabbing")]\r
+        HRESULT SeamlessTabbing([in] VARIANT_BOOL pVal);\r
+        [id(0x000000c1), helpstring("method EnforceLocalSecurity")]\r
+        HRESULT EnforceLocalSecurity();\r
+        [id(0x000000c2), propget, helpstring("property Profile")]\r
+        HRESULT Profile([out, retval] VARIANT_BOOL* pVal);\r
+        [id(0x000000c2), propput, helpstring("property Profile")]\r
+        HRESULT Profile([in] VARIANT_BOOL pVal);\r
+        [id(0x000000c3), propget, helpstring("property ProfileAddress")]\r
+        HRESULT ProfileAddress([out, retval] BSTR* pVal);\r
+        [id(0x000000c3), propput, helpstring("property ProfileAddress")]\r
+        HRESULT ProfileAddress([in] BSTR pVal);\r
+        [id(0x000000c4), propget, helpstring("property ProfilePort")]\r
+        HRESULT ProfilePort([out, retval] long* pVal);\r
+        [id(0x000000c4), propput, helpstring("property ProfilePort")]\r
+        HRESULT ProfilePort([in] long pVal);\r
+        [id(0x000000c6), helpstring("method Call")]\r
+        HRESULT CallFunction(\r
+                        [in] BSTR request, \r
+                        [out, retval] BSTR* response);\r
+        [id(0x000000c7), helpstring("method SetReturnValue")]\r
+        HRESULT SetReturnValue([in] BSTR returnValue);\r
+        [id(0x000000c8), helpstring("method DisableLocalSecurity")]\r
+        HRESULT DisableLocalSecurity();\r
+        [id(0x000000c9), propget, helpstring("property AllowNetworking")]\r
+        HRESULT AllowNetworking([out, retval] BSTR* pVal);\r
+        [id(0x000000c9), propput, helpstring("property AllowNetworking")]\r
+        HRESULT AllowNetworking([in] BSTR pVal);\r
+        [id(0x000000ca), propget, helpstring("property AllowFullScreen")]\r
+        HRESULT AllowFullScreen([out, retval] BSTR* pVal);\r
+        [id(0x000000ca), propput, helpstring("property AllowFullScreen")]\r
+        HRESULT AllowFullScreen([in] BSTR pVal);\r
+    };\r
+\r
+    [\r
+      uuid(D27CDB6D-AE6D-11CF-96B8-444553540000),\r
+      helpstring("Event interface for Shockwave Flash"),\r
+         hidden\r
+    ]\r
+    dispinterface _IShockwaveFlashEvents {\r
+        properties:\r
+        methods:\r
+            [id(0xfffffd9f)]\r
+            void OnReadyStateChange(long newState);\r
+            [id(0x000007a6)]\r
+            void OnProgress(long percentDone);\r
+            [id(0x00000096)]\r
+            void FSCommand(\r
+                            [in] BSTR command, \r
+                            [in] BSTR args);\r
+            [id(0x000000c5)]\r
+            void FlashCall([in] BSTR request);\r
+    };\r
+\r
+    [\r
+      uuid(D27CDB6E-AE6D-11CF-96B8-444553540000),\r
+      helpstring("Shockwave Flash")\r
+    ]\r
+    coclass ShockwaveFlash {\r
+        [default] interface IShockwaveFlash;\r
+        [default, source] dispinterface _IShockwaveFlashEvents;\r
+    };\r
+\r
+    [\r
+      odl,\r
+      uuid(D27CDB70-AE6D-11CF-96B8-444553540000),\r
+      helpstring("IFlashFactory Interface")\r
+    ]\r
+    interface IFlashFactory : IUnknown {\r
+    };\r
+\r
+    [\r
+      odl,\r
+      uuid(D27CDB72-AE6D-11CF-96B8-444553540000),\r
+      helpstring("IFlashObjectInterface Interface")\r
+    ]\r
+    interface IFlashObjectInterface : IDispatchEx {\r
+    };\r
+\r
+    [\r
+      odl,\r
+      uuid(A6EF9860-C720-11D0-9337-00A0C90DCAA9)\r
+    ]\r
+    interface IDispatchEx : IDispatch {\r
+        HRESULT _stdcall GetDispID(\r
+                        [in] BSTR bstrName, \r
+                        [in] unsigned long grfdex, \r
+                        [out] long* pid);\r
+        HRESULT _stdcall RemoteInvokeEx(\r
+                        [in] long id, \r
+                        [in] unsigned long lcid, \r
+                        [in] unsigned long dwFlags, \r
+                        [in] DISPPARAMS* pdp, \r
+                        [out] VARIANT* pvarRes, \r
+                        [out] EXCEPINFO* pei, \r
+                        [in] IServiceProvider* pspCaller, \r
+                        [in] unsigned int cvarRefArg, \r
+                        [in] unsigned int* rgiRefArg, \r
+                        [in, out] VARIANT* rgvarRefArg);\r
+        HRESULT _stdcall DeleteMemberByName(\r
+                        [in] BSTR bstrName, \r
+                        [in] unsigned long grfdex);\r
+        HRESULT _stdcall DeleteMemberByDispID([in] long id);\r
+        HRESULT _stdcall GetMemberProperties(\r
+                        [in] long id, \r
+                        [in] unsigned long grfdexFetch, \r
+                        [out] unsigned long* pgrfdex);\r
+        HRESULT _stdcall GetMemberName(\r
+                        [in] long id, \r
+                        [out] BSTR* pbstrName);\r
+        HRESULT _stdcall GetNextDispID(\r
+                        [in] unsigned long grfdex, \r
+                        [in] long id, \r
+                        [out] long* pid);\r
+        HRESULT _stdcall GetNameSpaceParent([out] IUnknown** ppunk);\r
+    };\r
+\r
+    [\r
+      odl,\r
+      uuid(6D5140C1-7436-11CE-8034-00AA006009FA)\r
+    ]\r
+    interface IServiceProvider : IUnknown {\r
+        HRESULT _stdcall RemoteQueryService(\r
+                        [in] GUID* guidService, \r
+                        [in] GUID* riid, \r
+                        [out] IUnknown** ppvObject);\r
+    };\r
+\r
+    [\r
+      uuid(D27CDB71-AE6D-11CF-96B8-444553540000),\r
+      helpstring("IFlashObjectInterface Interface")\r
+    ]\r
+    coclass FlashObjectInterface {\r
+        [default] interface IFlashObjectInterface;\r
+    };\r
+};\r
diff --git a/modules/flash/interop/Flash9e_i.c b/modules/flash/interop/Flash9e_i.c
new file mode 100644 (file)
index 0000000..3cc610e
--- /dev/null
@@ -0,0 +1,103 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */\r
+\r
+/* link this file in with the server and any clients */\r
+\r
+\r
+ /* File created by MIDL compiler version 6.00.0366 */\r
+/* at Tue Mar 18 13:05:00 2008\r
+ */\r
+/* Compiler settings for .\flash\Flash9e.IDL:\r
+    Oicf, W4, Zp8, env=Win32 (32b run)\r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+//@@MIDL_FILE_HEADING(  )\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif \r
+\r
+\r
+#include <rpc.h>\r
+#include <rpcndr.h>\r
+\r
+#ifdef _MIDL_USE_GUIDDEF_\r
+\r
+#ifndef INITGUID\r
+#define INITGUID\r
+#include <guiddef.h>\r
+#undef INITGUID\r
+#else\r
+#include <guiddef.h>\r
+#endif\r
+\r
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\r
+        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\r
+\r
+#else // !_MIDL_USE_GUIDDEF_\r
+\r
+#ifndef __IID_DEFINED__\r
+#define __IID_DEFINED__\r
+\r
+typedef struct _IID\r
+{\r
+    unsigned long x;\r
+    unsigned short s1;\r
+    unsigned short s2;\r
+    unsigned char  c[8];\r
+} IID;\r
+\r
+#endif // __IID_DEFINED__\r
+\r
+#ifndef CLSID_DEFINED\r
+#define CLSID_DEFINED\r
+typedef IID CLSID;\r
+#endif // CLSID_DEFINED\r
+\r
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\r
+        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\r
+\r
+#endif !_MIDL_USE_GUIDDEF_\r
+\r
+MIDL_DEFINE_GUID(IID, LIBID_ShockwaveFlashObjects,0xD27CDB6B,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IShockwaveFlash,0xD27CDB6C,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, DIID__IShockwaveFlashEvents,0xD27CDB6D,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IFlashFactory,0xD27CDB70,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IDispatchEx,0xA6EF9860,0xC720,0x11D0,0x93,0x37,0x00,0xA0,0xC9,0x0D,0xCA,0xA9);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IFlashObjectInterface,0xD27CDB72,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IServiceProvider,0x6D5140C1,0x7436,0x11CE,0x80,0x34,0x00,0xAA,0x00,0x60,0x09,0xFA);\r
+\r
+\r
+MIDL_DEFINE_GUID(CLSID, CLSID_ShockwaveFlash,0xD27CDB6E,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+\r
+MIDL_DEFINE_GUID(CLSID, CLSID_FlashObjectInterface,0xD27CDB71,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\r
+\r
+#undef MIDL_DEFINE_GUID\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+\r
diff --git a/modules/flash/interop/TimerHelper.h b/modules/flash/interop/TimerHelper.h
new file mode 100644 (file)
index 0000000..a0de2b1
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
\r
+#ifndef _TIMER_HELPER_H__\r
+#define _TIMER_HELPER_H__\r
+\r
+#include "FlashAxContainer.h"\r
+\r
+namespace caspar {\r
+namespace flash {\r
+\r
+       class TimerHelper\r
+       {\r
+               TimerHelper(const TimerHelper&);\r
+               const TimerHelper& operator=(const TimerHelper&);\r
+\r
+       public:\r
+               TimerHelper()\r
+               {}\r
+               TimerHelper(DWORD first, DWORD interv, ITimerSink* pTS) : firstTime(first), interval(interv), currentTime(first), pTimerSink(pTS)\r
+               {\r
+                       ID = first;\r
+               }\r
+               ~TimerHelper()\r
+               {\r
+               }\r
+               void Setup(DWORD first, DWORD interv, ITimerSink* pTS)\r
+               {\r
+                       firstTime = first;\r
+                       interval = interv;\r
+                       currentTime = first;\r
+                       pTimerSink = pTS;\r
+                       ID = first;\r
+               }\r
+\r
+               DWORD Invoke()\r
+               {\r
+                       if(pTimerSink != 0)\r
+                       {\r
+                               VARIANT value;\r
+                               value.vt = VT_UI4;\r
+                               value.ulVal = currentTime;\r
+\r
+                               pTimerSink->OnTimer(value);\r
+                               currentTime += interval;\r
+                       }\r
+                       return currentTime;\r
+               }\r
+\r
+               DWORD firstTime;\r
+               DWORD interval;\r
+               DWORD currentTime;\r
+               ATL::CComPtr<ITimerSink> pTimerSink;\r
+               DWORD ID;\r
+       };\r
+\r
+}      //namespace flash\r
+}      //namespace caspar\r
+\r
+#endif //_TIMER_HELPER_H__
\ No newline at end of file
diff --git a/modules/flash/interop/axflash.h b/modules/flash/interop/axflash.h
new file mode 100644 (file)
index 0000000..da7aa8b
--- /dev/null
@@ -0,0 +1,3156 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */\r
+\r
+\r
+ /* File created by MIDL compiler version 6.00.0366 */\r
+/* at Tue Mar 18 13:05:00 2008\r
+ */\r
+/* Compiler settings for .\flash\Flash9e.IDL:\r
+    Oicf, W4, Zp8, env=Win32 (32b run)\r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+//@@MIDL_FILE_HEADING(  )\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+\r
+\r
+/* verify that the <rpcndr.h> version is high enough to compile this file*/\r
+#ifndef __REQUIRED_RPCNDR_H_VERSION__\r
+#define __REQUIRED_RPCNDR_H_VERSION__ 475\r
+#endif\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+#include <dispex.h>\r
+\r
+#ifndef __RPCNDR_H_VERSION__\r
+#error this stub requires an updated version of <rpcndr.h>\r
+#endif // __RPCNDR_H_VERSION__\r
+\r
+\r
+#ifndef __axflash_h__\r
+#define __axflash_h__\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+#pragma once\r
+#endif\r
+\r
+/* Forward Declarations */ \r
+\r
+#ifndef __IShockwaveFlash_FWD_DEFINED__\r
+#define __IShockwaveFlash_FWD_DEFINED__\r
+typedef interface IShockwaveFlash IShockwaveFlash;\r
+#endif         /* __IShockwaveFlash_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef ___IShockwaveFlashEvents_FWD_DEFINED__\r
+#define ___IShockwaveFlashEvents_FWD_DEFINED__\r
+typedef interface _IShockwaveFlashEvents _IShockwaveFlashEvents;\r
+#endif         /* ___IShockwaveFlashEvents_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IFlashFactory_FWD_DEFINED__\r
+#define __IFlashFactory_FWD_DEFINED__\r
+typedef interface IFlashFactory IFlashFactory;\r
+#endif         /* __IFlashFactory_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IDispatchEx_FWD_DEFINED__\r
+#define __IDispatchEx_FWD_DEFINED__\r
+typedef interface IDispatchEx IDispatchEx;\r
+#endif         /* __IDispatchEx_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IFlashObjectInterface_FWD_DEFINED__\r
+#define __IFlashObjectInterface_FWD_DEFINED__\r
+typedef interface IFlashObjectInterface IFlashObjectInterface;\r
+#endif         /* __IFlashObjectInterface_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IServiceProvider_FWD_DEFINED__\r
+#define __IServiceProvider_FWD_DEFINED__\r
+typedef interface IServiceProvider IServiceProvider;\r
+#endif         /* __IServiceProvider_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __ShockwaveFlash_FWD_DEFINED__\r
+#define __ShockwaveFlash_FWD_DEFINED__\r
+\r
+#ifdef __cplusplus\r
+typedef class ShockwaveFlash ShockwaveFlash;\r
+#else\r
+typedef struct ShockwaveFlash ShockwaveFlash;\r
+#endif /* __cplusplus */\r
+\r
+#endif         /* __ShockwaveFlash_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __FlashObjectInterface_FWD_DEFINED__\r
+#define __FlashObjectInterface_FWD_DEFINED__\r
+\r
+#ifdef __cplusplus\r
+typedef class FlashObjectInterface FlashObjectInterface;\r
+#else\r
+typedef struct FlashObjectInterface FlashObjectInterface;\r
+#endif /* __cplusplus */\r
+\r
+#endif         /* __FlashObjectInterface_FWD_DEFINED__ */\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif \r
+\r
+void * __RPC_USER MIDL_user_allocate(size_t);\r
+void __RPC_USER MIDL_user_free( void * ); \r
+\r
+\r
+#ifndef __ShockwaveFlashObjects_LIBRARY_DEFINED__\r
+#define __ShockwaveFlashObjects_LIBRARY_DEFINED__\r
+\r
+/* library ShockwaveFlashObjects */\r
+/* [custom][custom][helpstring][version][uuid] */ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+EXTERN_C const IID LIBID_ShockwaveFlashObjects;\r
+\r
+#ifndef __IShockwaveFlash_INTERFACE_DEFINED__\r
+#define __IShockwaveFlash_INTERFACE_DEFINED__\r
+\r
+/* interface IShockwaveFlash */\r
+/* [object][oleautomation][dual][helpstring][uuid] */ \r
+\r
+\r
+EXTERN_C const IID IID_IShockwaveFlash;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("D27CDB6C-AE6D-11CF-96B8-444553540000")\r
+    IShockwaveFlash : public IDispatch\r
+    {\r
+    public:\r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ReadyState( \r
+            /* [retval][out] */ long *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_TotalFrames( \r
+            /* [retval][out] */ long *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Playing( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Playing( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Quality( \r
+            /* [retval][out] */ int *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Quality( \r
+            /* [in] */ int pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ScaleMode( \r
+            /* [retval][out] */ int *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ScaleMode( \r
+            /* [in] */ int pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AlignMode( \r
+            /* [retval][out] */ int *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AlignMode( \r
+            /* [in] */ int pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_BackgroundColor( \r
+            /* [retval][out] */ long *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_BackgroundColor( \r
+            /* [in] */ long pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Loop( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Loop( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Movie( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Movie( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE receiveNum( \r
+            /* [retval][out] */ long *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FrameNum( \r
+            /* [in] */ long pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetZoomRect( \r
+            /* [in] */ long left,\r
+            /* [in] */ long top,\r
+            /* [in] */ long right,\r
+            /* [in] */ long bottom) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Zoom( \r
+            /* [in] */ int factor) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Pan( \r
+            /* [in] */ long x,\r
+            /* [in] */ long y,\r
+            /* [in] */ int mode) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Play( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Back( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Forward( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE StopPlay( void) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GotoFrame( \r
+            /* [in] */ long FrameNum) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CurrentFrame( \r
+            /* [retval][out] */ long *FrameNum) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IsPlaying( \r
+            /* [retval][out] */ VARIANT_BOOL *Playing) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE PercentLoaded( \r
+            /* [retval][out] */ long *percent) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FrameLoaded( \r
+            /* [in] */ long FrameNum,\r
+            /* [retval][out] */ VARIANT_BOOL *loaded) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FlashVersion( \r
+            /* [retval][out] */ long *version) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_WMode( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_WMode( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SAlign( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SAlign( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Menu( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Menu( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Base( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Base( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Scale( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Scale( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_DeviceFont( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_DeviceFont( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_EmbedMovie( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_EmbedMovie( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_BGColor( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_BGColor( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Quality2( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Quality2( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE LoadMovie( \r
+            /* [in] */ int layer,\r
+            /* [in] */ BSTR url) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGotoFrame( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ long FrameNum) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGotoLabel( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ BSTR label) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCurrentFrame( \r
+            /* [in] */ BSTR target,\r
+            /* [retval][out] */ long *FrameNum) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCurrentLabel( \r
+            /* [in] */ BSTR target,\r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TPlay( \r
+            /* [in] */ BSTR target) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TStopPlay( \r
+            /* [in] */ BSTR target) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetVariable( \r
+            /* [in] */ BSTR name,\r
+            /* [in] */ BSTR value) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetVariable( \r
+            /* [in] */ BSTR name,\r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TSetProperty( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [in] */ BSTR value) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetProperty( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCallFrame( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int FrameNum) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCallLabel( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ BSTR label) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TSetPropertyNum( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [in] */ double value) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetPropertyNum( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ double *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetPropertyAsNumber( \r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ double *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SWRemote( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SWRemote( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_FlashVars( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FlashVars( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowScriptAccess( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowScriptAccess( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_MovieData( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_MovieData( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_InlineData( \r
+            /* [retval][out] */ IUnknown **ppIUnknown) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_InlineData( \r
+            /* [in] */ IUnknown *ppIUnknown) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SeamlessTabbing( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SeamlessTabbing( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE EnforceLocalSecurity( void) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Profile( \r
+            /* [retval][out] */ VARIANT_BOOL *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Profile( \r
+            /* [in] */ VARIANT_BOOL pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ProfileAddress( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ProfileAddress( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ProfilePort( \r
+            /* [retval][out] */ long *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ProfilePort( \r
+            /* [in] */ long pVal) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CallFunction( \r
+            /* [in] */ BSTR request,\r
+            /* [retval][out] */ BSTR *response) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetReturnValue( \r
+            /* [in] */ BSTR returnValue) = 0;\r
+        \r
+        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE DisableLocalSecurity( void) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowNetworking( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowNetworking( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowFullScreen( \r
+            /* [retval][out] */ BSTR *pVal) = 0;\r
+        \r
+        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowFullScreen( \r
+            /* [in] */ BSTR pVal) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IShockwaveFlashVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IShockwaveFlash * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IShockwaveFlash * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IShockwaveFlash * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ReadyState )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_TotalFrames )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Playing )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Playing )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Quality )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ int *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Quality )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ int pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ScaleMode )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ int *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ScaleMode )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ int pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AlignMode )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ int *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AlignMode )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ int pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_BackgroundColor )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_BackgroundColor )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Loop )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Loop )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Movie )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Movie )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *receiveNum )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_FrameNum )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SetZoomRect )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long left,\r
+            /* [in] */ long top,\r
+            /* [in] */ long right,\r
+            /* [in] */ long bottom);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Zoom )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ int factor);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Pan )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long x,\r
+            /* [in] */ long y,\r
+            /* [in] */ int mode);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Play )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Stop )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Back )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Forward )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *StopPlay )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GotoFrame )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long FrameNum);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CurrentFrame )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *FrameNum);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *IsPlaying )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *Playing);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *PercentLoaded )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *percent);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *FrameLoaded )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long FrameNum,\r
+            /* [retval][out] */ VARIANT_BOOL *loaded);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *FlashVersion )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *version);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_WMode )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_WMode )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_SAlign )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_SAlign )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Menu )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Menu )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Base )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Base )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Scale )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Scale )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_DeviceFont )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_DeviceFont )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_EmbedMovie )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_EmbedMovie )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_BGColor )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_BGColor )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Quality2 )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Quality2 )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *LoadMovie )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ int layer,\r
+            /* [in] */ BSTR url);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TGotoFrame )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ long FrameNum);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TGotoLabel )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ BSTR label);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TCurrentFrame )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [retval][out] */ long *FrameNum);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TCurrentLabel )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TPlay )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TStopPlay )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SetVariable )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR name,\r
+            /* [in] */ BSTR value);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetVariable )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR name,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TSetProperty )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [in] */ BSTR value);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TGetProperty )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TCallFrame )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int FrameNum);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TCallLabel )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ BSTR label);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TSetPropertyNum )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [in] */ double value);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TGetPropertyNum )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ double *pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *TGetPropertyAsNumber )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR target,\r
+            /* [in] */ int property,\r
+            /* [retval][out] */ double *pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_SWRemote )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_SWRemote )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_FlashVars )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_FlashVars )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AllowScriptAccess )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AllowScriptAccess )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_MovieData )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_MovieData )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_InlineData )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ IUnknown **ppIUnknown);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_InlineData )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ IUnknown *ppIUnknown);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_SeamlessTabbing )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_SeamlessTabbing )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *EnforceLocalSecurity )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Profile )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Profile )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ VARIANT_BOOL pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ProfileAddress )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ProfileAddress )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ProfilePort )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ long *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ProfilePort )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ long pVal);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CallFunction )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR request,\r
+            /* [retval][out] */ BSTR *response);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SetReturnValue )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR returnValue);\r
+        \r
+        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *DisableLocalSecurity )( \r
+            IShockwaveFlash * This);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AllowNetworking )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AllowNetworking )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AllowFullScreen )( \r
+            IShockwaveFlash * This,\r
+            /* [retval][out] */ BSTR *pVal);\r
+        \r
+        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AllowFullScreen )( \r
+            IShockwaveFlash * This,\r
+            /* [in] */ BSTR pVal);\r
+        \r
+        END_INTERFACE\r
+    } IShockwaveFlashVtbl;\r
+\r
+    interface IShockwaveFlash\r
+    {\r
+        CONST_VTBL struct IShockwaveFlashVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IShockwaveFlash_QueryInterface(This,riid,ppvObject)    \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define IShockwaveFlash_AddRef(This)   \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define IShockwaveFlash_Release(This)  \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#define IShockwaveFlash_GetTypeInfoCount(This,pctinfo) \\r
+    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\r
+\r
+#define IShockwaveFlash_GetTypeInfo(This,iTInfo,lcid,ppTInfo)  \\r
+    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\r
+\r
+#define IShockwaveFlash_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)        \\r
+    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\r
+\r
+#define IShockwaveFlash_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)  \\r
+    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\r
+\r
+\r
+#define IShockwaveFlash_get_ReadyState(This,pVal)      \\r
+    (This)->lpVtbl -> get_ReadyState(This,pVal)\r
+\r
+#define IShockwaveFlash_get_TotalFrames(This,pVal)     \\r
+    (This)->lpVtbl -> get_TotalFrames(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Playing(This,pVal) \\r
+    (This)->lpVtbl -> get_Playing(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Playing(This,pVal) \\r
+    (This)->lpVtbl -> put_Playing(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Quality(This,pVal) \\r
+    (This)->lpVtbl -> get_Quality(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Quality(This,pVal) \\r
+    (This)->lpVtbl -> put_Quality(This,pVal)\r
+\r
+#define IShockwaveFlash_get_ScaleMode(This,pVal)       \\r
+    (This)->lpVtbl -> get_ScaleMode(This,pVal)\r
+\r
+#define IShockwaveFlash_put_ScaleMode(This,pVal)       \\r
+    (This)->lpVtbl -> put_ScaleMode(This,pVal)\r
+\r
+#define IShockwaveFlash_get_AlignMode(This,pVal)       \\r
+    (This)->lpVtbl -> get_AlignMode(This,pVal)\r
+\r
+#define IShockwaveFlash_put_AlignMode(This,pVal)       \\r
+    (This)->lpVtbl -> put_AlignMode(This,pVal)\r
+\r
+#define IShockwaveFlash_get_BackgroundColor(This,pVal) \\r
+    (This)->lpVtbl -> get_BackgroundColor(This,pVal)\r
+\r
+#define IShockwaveFlash_put_BackgroundColor(This,pVal) \\r
+    (This)->lpVtbl -> put_BackgroundColor(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Loop(This,pVal)    \\r
+    (This)->lpVtbl -> get_Loop(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Loop(This,pVal)    \\r
+    (This)->lpVtbl -> put_Loop(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Movie(This,pVal)   \\r
+    (This)->lpVtbl -> get_Movie(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Movie(This,pVal)   \\r
+    (This)->lpVtbl -> put_Movie(This,pVal)\r
+\r
+#define IShockwaveFlash_receiveNum(This,pVal)  \\r
+    (This)->lpVtbl -> receiveNum(This,pVal)\r
+\r
+#define IShockwaveFlash_put_FrameNum(This,pVal)        \\r
+    (This)->lpVtbl -> put_FrameNum(This,pVal)\r
+\r
+#define IShockwaveFlash_SetZoomRect(This,left,top,right,bottom)        \\r
+    (This)->lpVtbl -> SetZoomRect(This,left,top,right,bottom)\r
+\r
+#define IShockwaveFlash_Zoom(This,factor)      \\r
+    (This)->lpVtbl -> Zoom(This,factor)\r
+\r
+#define IShockwaveFlash_Pan(This,x,y,mode)     \\r
+    (This)->lpVtbl -> Pan(This,x,y,mode)\r
+\r
+#define IShockwaveFlash_Play(This)     \\r
+    (This)->lpVtbl -> Play(This)\r
+\r
+#define IShockwaveFlash_Stop(This)     \\r
+    (This)->lpVtbl -> Stop(This)\r
+\r
+#define IShockwaveFlash_Back(This)     \\r
+    (This)->lpVtbl -> Back(This)\r
+\r
+#define IShockwaveFlash_Forward(This)  \\r
+    (This)->lpVtbl -> Forward(This)\r
+\r
+#define IShockwaveFlash_Rewind(This)   \\r
+    (This)->lpVtbl -> Rewind(This)\r
+\r
+#define IShockwaveFlash_StopPlay(This) \\r
+    (This)->lpVtbl -> StopPlay(This)\r
+\r
+#define IShockwaveFlash_GotoFrame(This,FrameNum)       \\r
+    (This)->lpVtbl -> GotoFrame(This,FrameNum)\r
+\r
+#define IShockwaveFlash_CurrentFrame(This,FrameNum)    \\r
+    (This)->lpVtbl -> CurrentFrame(This,FrameNum)\r
+\r
+#define IShockwaveFlash_IsPlaying(This,Playing)        \\r
+    (This)->lpVtbl -> IsPlaying(This,Playing)\r
+\r
+#define IShockwaveFlash_PercentLoaded(This,percent)    \\r
+    (This)->lpVtbl -> PercentLoaded(This,percent)\r
+\r
+#define IShockwaveFlash_FrameLoaded(This,FrameNum,loaded)      \\r
+    (This)->lpVtbl -> FrameLoaded(This,FrameNum,loaded)\r
+\r
+#define IShockwaveFlash_FlashVersion(This,version)     \\r
+    (This)->lpVtbl -> FlashVersion(This,version)\r
+\r
+#define IShockwaveFlash_get_WMode(This,pVal)   \\r
+    (This)->lpVtbl -> get_WMode(This,pVal)\r
+\r
+#define IShockwaveFlash_put_WMode(This,pVal)   \\r
+    (This)->lpVtbl -> put_WMode(This,pVal)\r
+\r
+#define IShockwaveFlash_get_SAlign(This,pVal)  \\r
+    (This)->lpVtbl -> get_SAlign(This,pVal)\r
+\r
+#define IShockwaveFlash_put_SAlign(This,pVal)  \\r
+    (This)->lpVtbl -> put_SAlign(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Menu(This,pVal)    \\r
+    (This)->lpVtbl -> get_Menu(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Menu(This,pVal)    \\r
+    (This)->lpVtbl -> put_Menu(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Base(This,pVal)    \\r
+    (This)->lpVtbl -> get_Base(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Base(This,pVal)    \\r
+    (This)->lpVtbl -> put_Base(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Scale(This,pVal)   \\r
+    (This)->lpVtbl -> get_Scale(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Scale(This,pVal)   \\r
+    (This)->lpVtbl -> put_Scale(This,pVal)\r
+\r
+#define IShockwaveFlash_get_DeviceFont(This,pVal)      \\r
+    (This)->lpVtbl -> get_DeviceFont(This,pVal)\r
+\r
+#define IShockwaveFlash_put_DeviceFont(This,pVal)      \\r
+    (This)->lpVtbl -> put_DeviceFont(This,pVal)\r
+\r
+#define IShockwaveFlash_get_EmbedMovie(This,pVal)      \\r
+    (This)->lpVtbl -> get_EmbedMovie(This,pVal)\r
+\r
+#define IShockwaveFlash_put_EmbedMovie(This,pVal)      \\r
+    (This)->lpVtbl -> put_EmbedMovie(This,pVal)\r
+\r
+#define IShockwaveFlash_get_BGColor(This,pVal) \\r
+    (This)->lpVtbl -> get_BGColor(This,pVal)\r
+\r
+#define IShockwaveFlash_put_BGColor(This,pVal) \\r
+    (This)->lpVtbl -> put_BGColor(This,pVal)\r
+\r
+#define IShockwaveFlash_get_Quality2(This,pVal)        \\r
+    (This)->lpVtbl -> get_Quality2(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Quality2(This,pVal)        \\r
+    (This)->lpVtbl -> put_Quality2(This,pVal)\r
+\r
+#define IShockwaveFlash_LoadMovie(This,layer,url)      \\r
+    (This)->lpVtbl -> LoadMovie(This,layer,url)\r
+\r
+#define IShockwaveFlash_TGotoFrame(This,target,FrameNum)       \\r
+    (This)->lpVtbl -> TGotoFrame(This,target,FrameNum)\r
+\r
+#define IShockwaveFlash_TGotoLabel(This,target,label)  \\r
+    (This)->lpVtbl -> TGotoLabel(This,target,label)\r
+\r
+#define IShockwaveFlash_TCurrentFrame(This,target,FrameNum)    \\r
+    (This)->lpVtbl -> TCurrentFrame(This,target,FrameNum)\r
+\r
+#define IShockwaveFlash_TCurrentLabel(This,target,pVal)        \\r
+    (This)->lpVtbl -> TCurrentLabel(This,target,pVal)\r
+\r
+#define IShockwaveFlash_TPlay(This,target)     \\r
+    (This)->lpVtbl -> TPlay(This,target)\r
+\r
+#define IShockwaveFlash_TStopPlay(This,target) \\r
+    (This)->lpVtbl -> TStopPlay(This,target)\r
+\r
+#define IShockwaveFlash_SetVariable(This,name,value)   \\r
+    (This)->lpVtbl -> SetVariable(This,name,value)\r
+\r
+#define IShockwaveFlash_GetVariable(This,name,pVal)    \\r
+    (This)->lpVtbl -> GetVariable(This,name,pVal)\r
+\r
+#define IShockwaveFlash_TSetProperty(This,target,property,value)       \\r
+    (This)->lpVtbl -> TSetProperty(This,target,property,value)\r
+\r
+#define IShockwaveFlash_TGetProperty(This,target,property,pVal)        \\r
+    (This)->lpVtbl -> TGetProperty(This,target,property,pVal)\r
+\r
+#define IShockwaveFlash_TCallFrame(This,target,FrameNum)       \\r
+    (This)->lpVtbl -> TCallFrame(This,target,FrameNum)\r
+\r
+#define IShockwaveFlash_TCallLabel(This,target,label)  \\r
+    (This)->lpVtbl -> TCallLabel(This,target,label)\r
+\r
+#define IShockwaveFlash_TSetPropertyNum(This,target,property,value)    \\r
+    (This)->lpVtbl -> TSetPropertyNum(This,target,property,value)\r
+\r
+#define IShockwaveFlash_TGetPropertyNum(This,target,property,pVal)     \\r
+    (This)->lpVtbl -> TGetPropertyNum(This,target,property,pVal)\r
+\r
+#define IShockwaveFlash_TGetPropertyAsNumber(This,target,property,pVal)        \\r
+    (This)->lpVtbl -> TGetPropertyAsNumber(This,target,property,pVal)\r
+\r
+#define IShockwaveFlash_get_SWRemote(This,pVal)        \\r
+    (This)->lpVtbl -> get_SWRemote(This,pVal)\r
+\r
+#define IShockwaveFlash_put_SWRemote(This,pVal)        \\r
+    (This)->lpVtbl -> put_SWRemote(This,pVal)\r
+\r
+#define IShockwaveFlash_get_FlashVars(This,pVal)       \\r
+    (This)->lpVtbl -> get_FlashVars(This,pVal)\r
+\r
+#define IShockwaveFlash_put_FlashVars(This,pVal)       \\r
+    (This)->lpVtbl -> put_FlashVars(This,pVal)\r
+\r
+#define IShockwaveFlash_get_AllowScriptAccess(This,pVal)       \\r
+    (This)->lpVtbl -> get_AllowScriptAccess(This,pVal)\r
+\r
+#define IShockwaveFlash_put_AllowScriptAccess(This,pVal)       \\r
+    (This)->lpVtbl -> put_AllowScriptAccess(This,pVal)\r
+\r
+#define IShockwaveFlash_get_MovieData(This,pVal)       \\r
+    (This)->lpVtbl -> get_MovieData(This,pVal)\r
+\r
+#define IShockwaveFlash_put_MovieData(This,pVal)       \\r
+    (This)->lpVtbl -> put_MovieData(This,pVal)\r
+\r
+#define IShockwaveFlash_get_InlineData(This,ppIUnknown)        \\r
+    (This)->lpVtbl -> get_InlineData(This,ppIUnknown)\r
+\r
+#define IShockwaveFlash_put_InlineData(This,ppIUnknown)        \\r
+    (This)->lpVtbl -> put_InlineData(This,ppIUnknown)\r
+\r
+#define IShockwaveFlash_get_SeamlessTabbing(This,pVal) \\r
+    (This)->lpVtbl -> get_SeamlessTabbing(This,pVal)\r
+\r
+#define IShockwaveFlash_put_SeamlessTabbing(This,pVal) \\r
+    (This)->lpVtbl -> put_SeamlessTabbing(This,pVal)\r
+\r
+#define IShockwaveFlash_EnforceLocalSecurity(This)     \\r
+    (This)->lpVtbl -> EnforceLocalSecurity(This)\r
+\r
+#define IShockwaveFlash_get_Profile(This,pVal) \\r
+    (This)->lpVtbl -> get_Profile(This,pVal)\r
+\r
+#define IShockwaveFlash_put_Profile(This,pVal) \\r
+    (This)->lpVtbl -> put_Profile(This,pVal)\r
+\r
+#define IShockwaveFlash_get_ProfileAddress(This,pVal)  \\r
+    (This)->lpVtbl -> get_ProfileAddress(This,pVal)\r
+\r
+#define IShockwaveFlash_put_ProfileAddress(This,pVal)  \\r
+    (This)->lpVtbl -> put_ProfileAddress(This,pVal)\r
+\r
+#define IShockwaveFlash_get_ProfilePort(This,pVal)     \\r
+    (This)->lpVtbl -> get_ProfilePort(This,pVal)\r
+\r
+#define IShockwaveFlash_put_ProfilePort(This,pVal)     \\r
+    (This)->lpVtbl -> put_ProfilePort(This,pVal)\r
+\r
+#define IShockwaveFlash_CallFunction(This,request,response)    \\r
+    (This)->lpVtbl -> CallFunction(This,request,response)\r
+\r
+#define IShockwaveFlash_SetReturnValue(This,returnValue)       \\r
+    (This)->lpVtbl -> SetReturnValue(This,returnValue)\r
+\r
+#define IShockwaveFlash_DisableLocalSecurity(This)     \\r
+    (This)->lpVtbl -> DisableLocalSecurity(This)\r
+\r
+#define IShockwaveFlash_get_AllowNetworking(This,pVal) \\r
+    (This)->lpVtbl -> get_AllowNetworking(This,pVal)\r
+\r
+#define IShockwaveFlash_put_AllowNetworking(This,pVal) \\r
+    (This)->lpVtbl -> put_AllowNetworking(This,pVal)\r
+\r
+#define IShockwaveFlash_get_AllowFullScreen(This,pVal) \\r
+    (This)->lpVtbl -> get_AllowFullScreen(This,pVal)\r
+\r
+#define IShockwaveFlash_put_AllowFullScreen(This,pVal) \\r
+    (This)->lpVtbl -> put_AllowFullScreen(This,pVal)\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_ReadyState_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_ReadyState_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_TotalFrames_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_TotalFrames_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Playing_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Playing_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Playing_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Playing_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Quality_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ int *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Quality_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Quality_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ int pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Quality_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_ScaleMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ int *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_ScaleMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_ScaleMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ int pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_ScaleMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_AlignMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ int *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_AlignMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_AlignMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ int pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_AlignMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_BackgroundColor_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_BackgroundColor_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_BackgroundColor_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_BackgroundColor_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Loop_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Loop_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Loop_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Loop_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Movie_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Movie_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Movie_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Movie_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_receiveNum_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_receiveNum_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_FrameNum_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_FrameNum_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetZoomRect_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long left,\r
+    /* [in] */ long top,\r
+    /* [in] */ long right,\r
+    /* [in] */ long bottom);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_SetZoomRect_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Zoom_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ int factor);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Zoom_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Pan_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long x,\r
+    /* [in] */ long y,\r
+    /* [in] */ int mode);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Pan_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Play_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Play_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Stop_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Stop_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Back_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Back_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Forward_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Forward_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Rewind_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_Rewind_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_StopPlay_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_StopPlay_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_GotoFrame_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long FrameNum);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_GotoFrame_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_CurrentFrame_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *FrameNum);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_CurrentFrame_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_IsPlaying_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *Playing);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_IsPlaying_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_PercentLoaded_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *percent);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_PercentLoaded_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_FrameLoaded_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long FrameNum,\r
+    /* [retval][out] */ VARIANT_BOOL *loaded);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_FrameLoaded_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_FlashVersion_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *version);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_FlashVersion_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_WMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_WMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_WMode_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_WMode_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_SAlign_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_SAlign_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_SAlign_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_SAlign_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Menu_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Menu_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Menu_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Menu_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Base_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Base_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Base_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Base_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Scale_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Scale_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Scale_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Scale_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_DeviceFont_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_DeviceFont_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_DeviceFont_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_DeviceFont_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_EmbedMovie_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_EmbedMovie_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_EmbedMovie_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_EmbedMovie_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_BGColor_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_BGColor_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_BGColor_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_BGColor_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Quality2_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Quality2_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Quality2_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Quality2_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_LoadMovie_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ int layer,\r
+    /* [in] */ BSTR url);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_LoadMovie_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGotoFrame_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ long FrameNum);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TGotoFrame_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGotoLabel_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ BSTR label);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TGotoLabel_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCurrentFrame_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [retval][out] */ long *FrameNum);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TCurrentFrame_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCurrentLabel_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TCurrentLabel_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TPlay_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TPlay_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TStopPlay_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TStopPlay_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetVariable_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR name,\r
+    /* [in] */ BSTR value);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_SetVariable_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_GetVariable_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR name,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_GetVariable_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TSetProperty_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int property,\r
+    /* [in] */ BSTR value);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TSetProperty_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGetProperty_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int property,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TGetProperty_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCallFrame_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int FrameNum);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TCallFrame_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCallLabel_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ BSTR label);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TCallLabel_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TSetPropertyNum_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int property,\r
+    /* [in] */ double value);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TSetPropertyNum_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGetPropertyNum_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int property,\r
+    /* [retval][out] */ double *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TGetPropertyNum_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGetPropertyAsNumber_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR target,\r
+    /* [in] */ int property,\r
+    /* [retval][out] */ double *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_TGetPropertyAsNumber_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_SWRemote_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_SWRemote_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_SWRemote_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_SWRemote_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_FlashVars_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_FlashVars_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_FlashVars_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_FlashVars_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_AllowScriptAccess_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_AllowScriptAccess_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_AllowScriptAccess_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_AllowScriptAccess_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_MovieData_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_MovieData_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_MovieData_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_MovieData_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_InlineData_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ IUnknown **ppIUnknown);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_InlineData_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_InlineData_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ IUnknown *ppIUnknown);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_InlineData_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_SeamlessTabbing_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_SeamlessTabbing_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_SeamlessTabbing_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_SeamlessTabbing_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_EnforceLocalSecurity_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_EnforceLocalSecurity_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_Profile_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ VARIANT_BOOL *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_Profile_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Profile_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ VARIANT_BOOL pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_Profile_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_ProfileAddress_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_ProfileAddress_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_ProfileAddress_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_ProfileAddress_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_ProfilePort_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ long *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_ProfilePort_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_ProfilePort_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ long pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_ProfilePort_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_CallFunction_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR request,\r
+    /* [retval][out] */ BSTR *response);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_CallFunction_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetReturnValue_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR returnValue);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_SetReturnValue_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_DisableLocalSecurity_Proxy( \r
+    IShockwaveFlash * This);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_DisableLocalSecurity_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_AllowNetworking_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_AllowNetworking_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_AllowNetworking_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_AllowNetworking_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_AllowFullScreen_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [retval][out] */ BSTR *pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_get_AllowFullScreen_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_AllowFullScreen_Proxy( \r
+    IShockwaveFlash * This,\r
+    /* [in] */ BSTR pVal);\r
+\r
+\r
+void __RPC_STUB IShockwaveFlash_put_AllowFullScreen_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+\r
+#endif         /* __IShockwaveFlash_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__\r
+#define ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__\r
+\r
+/* dispinterface _IShockwaveFlashEvents */\r
+/* [hidden][helpstring][uuid] */ \r
+\r
+\r
+EXTERN_C const IID DIID__IShockwaveFlashEvents;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+\r
+    MIDL_INTERFACE("D27CDB6D-AE6D-11CF-96B8-444553540000")\r
+    _IShockwaveFlashEvents : public IDispatch\r
+    {\r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct _IShockwaveFlashEventsVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            _IShockwaveFlashEvents * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            _IShockwaveFlashEvents * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            _IShockwaveFlashEvents * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            _IShockwaveFlashEvents * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            _IShockwaveFlashEvents * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            _IShockwaveFlashEvents * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            _IShockwaveFlashEvents * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        END_INTERFACE\r
+    } _IShockwaveFlashEventsVtbl;\r
+\r
+    interface _IShockwaveFlashEvents\r
+    {\r
+        CONST_VTBL struct _IShockwaveFlashEventsVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define _IShockwaveFlashEvents_QueryInterface(This,riid,ppvObject)     \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define _IShockwaveFlashEvents_AddRef(This)    \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define _IShockwaveFlashEvents_Release(This)   \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#define _IShockwaveFlashEvents_GetTypeInfoCount(This,pctinfo)  \\r
+    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\r
+\r
+#define _IShockwaveFlashEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo)   \\r
+    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\r
+\r
+#define _IShockwaveFlashEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \\r
+    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\r
+\r
+#define _IShockwaveFlashEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)   \\r
+    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+#endif         /* ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IFlashFactory_INTERFACE_DEFINED__\r
+#define __IFlashFactory_INTERFACE_DEFINED__\r
+\r
+/* interface IFlashFactory */\r
+/* [object][helpstring][uuid] */ \r
+\r
+\r
+EXTERN_C const IID IID_IFlashFactory;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("D27CDB70-AE6D-11CF-96B8-444553540000")\r
+    IFlashFactory : public IUnknown\r
+    {\r
+    public:\r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IFlashFactoryVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IFlashFactory * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IFlashFactory * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IFlashFactory * This);\r
+        \r
+        END_INTERFACE\r
+    } IFlashFactoryVtbl;\r
+\r
+    interface IFlashFactory\r
+    {\r
+        CONST_VTBL struct IFlashFactoryVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IFlashFactory_QueryInterface(This,riid,ppvObject)      \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define IFlashFactory_AddRef(This)     \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define IFlashFactory_Release(This)    \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IFlashFactory_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IFlashObjectInterface_INTERFACE_DEFINED__\r
+#define __IFlashObjectInterface_INTERFACE_DEFINED__\r
+\r
+/* interface IFlashObjectInterface */\r
+/* [object][helpstring][uuid] */ \r
+\r
+\r
+EXTERN_C const IID IID_IFlashObjectInterface;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("D27CDB72-AE6D-11CF-96B8-444553540000")\r
+    IFlashObjectInterface : public IDispatchEx\r
+    {\r
+    public:\r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IFlashObjectInterfaceVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IFlashObjectInterface * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IFlashObjectInterface * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IFlashObjectInterface * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        HRESULT ( __stdcall *GetDispID )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex,\r
+            /* [out] */ long *pid);\r
+        \r
+        HRESULT ( __stdcall *RemoteInvokeEx )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long lcid,\r
+            /* [in] */ unsigned long dwFlags,\r
+            /* [in] */ DISPPARAMS *pdp,\r
+            /* [out] */ VARIANT *pvarRes,\r
+            /* [out] */ EXCEPINFO *pei,\r
+            /* [in] */ IServiceProvider *pspCaller,\r
+            /* [in] */ unsigned int cvarRefArg,\r
+            /* [in] */ unsigned int *rgiRefArg,\r
+            /* [out][in] */ VARIANT *rgvarRefArg);\r
+        \r
+        HRESULT ( __stdcall *DeleteMemberByName )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex);\r
+        \r
+        HRESULT ( __stdcall *DeleteMemberByDispID )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ long id);\r
+        \r
+        HRESULT ( __stdcall *GetMemberProperties )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long grfdexFetch,\r
+            /* [out] */ unsigned long *pgrfdex);\r
+        \r
+        HRESULT ( __stdcall *GetMemberName )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ long id,\r
+            /* [out] */ BSTR *pbstrName);\r
+        \r
+        HRESULT ( __stdcall *GetNextDispID )( \r
+            IFlashObjectInterface * This,\r
+            /* [in] */ unsigned long grfdex,\r
+            /* [in] */ long id,\r
+            /* [out] */ long *pid);\r
+        \r
+        HRESULT ( __stdcall *GetNameSpaceParent )( \r
+            IFlashObjectInterface * This,\r
+            /* [out] */ IUnknown **ppunk);\r
+        \r
+        END_INTERFACE\r
+    } IFlashObjectInterfaceVtbl;\r
+\r
+    interface IFlashObjectInterface\r
+    {\r
+        CONST_VTBL struct IFlashObjectInterfaceVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IFlashObjectInterface_QueryInterface(This,riid,ppvObject)      \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define IFlashObjectInterface_AddRef(This)     \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define IFlashObjectInterface_Release(This)    \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#define IFlashObjectInterface_GetTypeInfoCount(This,pctinfo)   \\r
+    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\r
+\r
+#define IFlashObjectInterface_GetTypeInfo(This,iTInfo,lcid,ppTInfo)    \\r
+    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\r
+\r
+#define IFlashObjectInterface_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)  \\r
+    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\r
+\r
+#define IFlashObjectInterface_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)    \\r
+    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\r
+\r
+\r
+#define IFlashObjectInterface_GetDispID(This,bstrName,grfdex,pid)      \\r
+    (This)->lpVtbl -> GetDispID(This,bstrName,grfdex,pid)\r
+\r
+#define IFlashObjectInterface_RemoteInvokeEx(This,id,lcid,dwFlags,pdp,pvarRes,pei,pspCaller,cvarRefArg,rgiRefArg,rgvarRefArg)  \\r
+    (This)->lpVtbl -> RemoteInvokeEx(This,id,lcid,dwFlags,pdp,pvarRes,pei,pspCaller,cvarRefArg,rgiRefArg,rgvarRefArg)\r
+\r
+#define IFlashObjectInterface_DeleteMemberByName(This,bstrName,grfdex) \\r
+    (This)->lpVtbl -> DeleteMemberByName(This,bstrName,grfdex)\r
+\r
+#define IFlashObjectInterface_DeleteMemberByDispID(This,id)    \\r
+    (This)->lpVtbl -> DeleteMemberByDispID(This,id)\r
+\r
+#define IFlashObjectInterface_GetMemberProperties(This,id,grfdexFetch,pgrfdex) \\r
+    (This)->lpVtbl -> GetMemberProperties(This,id,grfdexFetch,pgrfdex)\r
+\r
+#define IFlashObjectInterface_GetMemberName(This,id,pbstrName) \\r
+    (This)->lpVtbl -> GetMemberName(This,id,pbstrName)\r
+\r
+#define IFlashObjectInterface_GetNextDispID(This,grfdex,id,pid)        \\r
+    (This)->lpVtbl -> GetNextDispID(This,grfdex,id,pid)\r
+\r
+#define IFlashObjectInterface_GetNameSpaceParent(This,ppunk)   \\r
+    (This)->lpVtbl -> GetNameSpaceParent(This,ppunk)\r
+\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IFlashObjectInterface_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IDispatchEx_INTERFACE_DEFINED__\r
+#define __IDispatchEx_INTERFACE_DEFINED__\r
+\r
+/* interface IDispatchEx */\r
+/* [object][uuid] */ \r
+\r
+\r
+EXTERN_C const IID IID_IDispatchEx;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("A6EF9860-C720-11D0-9337-00A0C90DCAA9")\r
+    IDispatchEx : public IDispatch\r
+    {\r
+    public:\r
+        virtual HRESULT __stdcall GetDispID( \r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex,\r
+            /* [out] */ long *pid) = 0;\r
+        \r
+        virtual HRESULT __stdcall RemoteInvokeEx( \r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long lcid,\r
+            /* [in] */ unsigned long dwFlags,\r
+            /* [in] */ DISPPARAMS *pdp,\r
+            /* [out] */ VARIANT *pvarRes,\r
+            /* [out] */ EXCEPINFO *pei,\r
+            /* [in] */ IServiceProvider *pspCaller,\r
+            /* [in] */ unsigned int cvarRefArg,\r
+            /* [in] */ unsigned int *rgiRefArg,\r
+            /* [out][in] */ VARIANT *rgvarRefArg) = 0;\r
+        \r
+        virtual HRESULT __stdcall DeleteMemberByName( \r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex) = 0;\r
+        \r
+        virtual HRESULT __stdcall DeleteMemberByDispID( \r
+            /* [in] */ long id) = 0;\r
+        \r
+        virtual HRESULT __stdcall GetMemberProperties( \r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long grfdexFetch,\r
+            /* [out] */ unsigned long *pgrfdex) = 0;\r
+        \r
+        virtual HRESULT __stdcall GetMemberName( \r
+            /* [in] */ long id,\r
+            /* [out] */ BSTR *pbstrName) = 0;\r
+        \r
+        virtual HRESULT __stdcall GetNextDispID( \r
+            /* [in] */ unsigned long grfdex,\r
+            /* [in] */ long id,\r
+            /* [out] */ long *pid) = 0;\r
+        \r
+        virtual HRESULT __stdcall GetNameSpaceParent( \r
+            /* [out] */ IUnknown **ppunk) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IDispatchExVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IDispatchEx * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IDispatchEx * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IDispatchEx * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IDispatchEx * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IDispatchEx * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IDispatchEx * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IDispatchEx * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        HRESULT ( __stdcall *GetDispID )( \r
+            IDispatchEx * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex,\r
+            /* [out] */ long *pid);\r
+        \r
+        HRESULT ( __stdcall *RemoteInvokeEx )( \r
+            IDispatchEx * This,\r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long lcid,\r
+            /* [in] */ unsigned long dwFlags,\r
+            /* [in] */ DISPPARAMS *pdp,\r
+            /* [out] */ VARIANT *pvarRes,\r
+            /* [out] */ EXCEPINFO *pei,\r
+            /* [in] */ IServiceProvider *pspCaller,\r
+            /* [in] */ unsigned int cvarRefArg,\r
+            /* [in] */ unsigned int *rgiRefArg,\r
+            /* [out][in] */ VARIANT *rgvarRefArg);\r
+        \r
+        HRESULT ( __stdcall *DeleteMemberByName )( \r
+            IDispatchEx * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ unsigned long grfdex);\r
+        \r
+        HRESULT ( __stdcall *DeleteMemberByDispID )( \r
+            IDispatchEx * This,\r
+            /* [in] */ long id);\r
+        \r
+        HRESULT ( __stdcall *GetMemberProperties )( \r
+            IDispatchEx * This,\r
+            /* [in] */ long id,\r
+            /* [in] */ unsigned long grfdexFetch,\r
+            /* [out] */ unsigned long *pgrfdex);\r
+        \r
+        HRESULT ( __stdcall *GetMemberName )( \r
+            IDispatchEx * This,\r
+            /* [in] */ long id,\r
+            /* [out] */ BSTR *pbstrName);\r
+        \r
+        HRESULT ( __stdcall *GetNextDispID )( \r
+            IDispatchEx * This,\r
+            /* [in] */ unsigned long grfdex,\r
+            /* [in] */ long id,\r
+            /* [out] */ long *pid);\r
+        \r
+        HRESULT ( __stdcall *GetNameSpaceParent )( \r
+            IDispatchEx * This,\r
+            /* [out] */ IUnknown **ppunk);\r
+        \r
+        END_INTERFACE\r
+    } IDispatchExVtbl;\r
+\r
+    interface IDispatchEx\r
+    {\r
+        CONST_VTBL struct IDispatchExVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IDispatchEx_QueryInterface(This,riid,ppvObject)        \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define IDispatchEx_AddRef(This)       \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define IDispatchEx_Release(This)      \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#define IDispatchEx_GetTypeInfoCount(This,pctinfo)     \\r
+    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)\r
+\r
+#define IDispatchEx_GetTypeInfo(This,iTInfo,lcid,ppTInfo)      \\r
+    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)\r
+\r
+#define IDispatchEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)    \\r
+    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)\r
+\r
+#define IDispatchEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)      \\r
+    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)\r
+\r
+\r
+#define IDispatchEx_GetDispID(This,bstrName,grfdex,pid)        \\r
+    (This)->lpVtbl -> GetDispID(This,bstrName,grfdex,pid)\r
+\r
+#define IDispatchEx_RemoteInvokeEx(This,id,lcid,dwFlags,pdp,pvarRes,pei,pspCaller,cvarRefArg,rgiRefArg,rgvarRefArg)    \\r
+    (This)->lpVtbl -> RemoteInvokeEx(This,id,lcid,dwFlags,pdp,pvarRes,pei,pspCaller,cvarRefArg,rgiRefArg,rgvarRefArg)\r
+\r
+#define IDispatchEx_DeleteMemberByName(This,bstrName,grfdex)   \\r
+    (This)->lpVtbl -> DeleteMemberByName(This,bstrName,grfdex)\r
+\r
+#define IDispatchEx_DeleteMemberByDispID(This,id)      \\r
+    (This)->lpVtbl -> DeleteMemberByDispID(This,id)\r
+\r
+#define IDispatchEx_GetMemberProperties(This,id,grfdexFetch,pgrfdex)   \\r
+    (This)->lpVtbl -> GetMemberProperties(This,id,grfdexFetch,pgrfdex)\r
+\r
+#define IDispatchEx_GetMemberName(This,id,pbstrName)   \\r
+    (This)->lpVtbl -> GetMemberName(This,id,pbstrName)\r
+\r
+#define IDispatchEx_GetNextDispID(This,grfdex,id,pid)  \\r
+    (This)->lpVtbl -> GetNextDispID(This,grfdex,id,pid)\r
+\r
+#define IDispatchEx_GetNameSpaceParent(This,ppunk)     \\r
+    (This)->lpVtbl -> GetNameSpaceParent(This,ppunk)\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_GetDispID_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ BSTR bstrName,\r
+    /* [in] */ unsigned long grfdex,\r
+    /* [out] */ long *pid);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_GetDispID_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_RemoteInvokeEx_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ long id,\r
+    /* [in] */ unsigned long lcid,\r
+    /* [in] */ unsigned long dwFlags,\r
+    /* [in] */ DISPPARAMS *pdp,\r
+    /* [out] */ VARIANT *pvarRes,\r
+    /* [out] */ EXCEPINFO *pei,\r
+    /* [in] */ IServiceProvider *pspCaller,\r
+    /* [in] */ unsigned int cvarRefArg,\r
+    /* [in] */ unsigned int *rgiRefArg,\r
+    /* [out][in] */ VARIANT *rgvarRefArg);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_RemoteInvokeEx_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_DeleteMemberByName_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ BSTR bstrName,\r
+    /* [in] */ unsigned long grfdex);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_DeleteMemberByName_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_DeleteMemberByDispID_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ long id);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_DeleteMemberByDispID_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_GetMemberProperties_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ long id,\r
+    /* [in] */ unsigned long grfdexFetch,\r
+    /* [out] */ unsigned long *pgrfdex);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_GetMemberProperties_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_GetMemberName_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ long id,\r
+    /* [out] */ BSTR *pbstrName);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_GetMemberName_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_GetNextDispID_Proxy( \r
+    IDispatchEx * This,\r
+    /* [in] */ unsigned long grfdex,\r
+    /* [in] */ long id,\r
+    /* [out] */ long *pid);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_GetNextDispID_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+HRESULT __stdcall IDispatchEx_GetNameSpaceParent_Proxy( \r
+    IDispatchEx * This,\r
+    /* [out] */ IUnknown **ppunk);\r
+\r
+\r
+void __RPC_STUB IDispatchEx_GetNameSpaceParent_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+\r
+#endif         /* __IDispatchEx_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IServiceProvider_INTERFACE_DEFINED__\r
+#define __IServiceProvider_INTERFACE_DEFINED__\r
+\r
+/* interface IServiceProvider */\r
+/* [object][uuid] */ \r
+\r
+\r
+EXTERN_C const IID IID_IServiceProvider;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("6D5140C1-7436-11CE-8034-00AA006009FA")\r
+    IServiceProvider : public IUnknown\r
+    {\r
+    public:\r
+        virtual HRESULT __stdcall RemoteQueryService( \r
+            /* [in] */ GUID *guidService,\r
+            /* [in] */ GUID *riid,\r
+            /* [out] */ IUnknown **ppvObject) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IServiceProviderVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IServiceProvider * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [iid_is][out] */ void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IServiceProvider * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IServiceProvider * This);\r
+        \r
+        HRESULT ( __stdcall *RemoteQueryService )( \r
+            IServiceProvider * This,\r
+            /* [in] */ GUID *guidService,\r
+            /* [in] */ GUID *riid,\r
+            /* [out] */ IUnknown **ppvObject);\r
+        \r
+        END_INTERFACE\r
+    } IServiceProviderVtbl;\r
+\r
+    interface IServiceProvider\r
+    {\r
+        CONST_VTBL struct IServiceProviderVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IServiceProvider_QueryInterface(This,riid,ppvObject)   \\r
+    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)\r
+\r
+#define IServiceProvider_AddRef(This)  \\r
+    (This)->lpVtbl -> AddRef(This)\r
+\r
+#define IServiceProvider_Release(This) \\r
+    (This)->lpVtbl -> Release(This)\r
+\r
+\r
+#define IServiceProvider_RemoteQueryService(This,guidService,riid,ppvObject)   \\r
+    (This)->lpVtbl -> RemoteQueryService(This,guidService,riid,ppvObject)\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+HRESULT __stdcall IServiceProvider_RemoteQueryService_Proxy( \r
+    IServiceProvider * This,\r
+    /* [in] */ GUID *guidService,\r
+    /* [in] */ GUID *riid,\r
+    /* [out] */ IUnknown **ppvObject);\r
+\r
+\r
+void __RPC_STUB IServiceProvider_RemoteQueryService_Stub(\r
+    IRpcStubBuffer *This,\r
+    IRpcChannelBuffer *_pRpcChannelBuffer,\r
+    PRPC_MESSAGE _pRpcMessage,\r
+    DWORD *_pdwStubPhase);\r
+\r
+\r
+\r
+#endif         /* __IServiceProvider_INTERFACE_DEFINED__ */\r
+\r
+\r
+EXTERN_C const CLSID CLSID_ShockwaveFlash;\r
+\r
+#ifdef __cplusplus\r
+\r
+class DECLSPEC_UUID("D27CDB6E-AE6D-11CF-96B8-444553540000")\r
+ShockwaveFlash;\r
+#endif\r
+\r
+EXTERN_C const CLSID CLSID_FlashObjectInterface;\r
+\r
+#ifdef __cplusplus\r
+\r
+class DECLSPEC_UUID("D27CDB71-AE6D-11CF-96B8-444553540000")\r
+FlashObjectInterface;\r
+#endif\r
+#endif /* __ShockwaveFlashObjects_LIBRARY_DEFINED__ */\r
+\r
+/* Additional Prototypes for ALL interfaces */\r
+\r
+/* end of Additional Prototypes */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
diff --git a/modules/flash/producer/FlashAxContainer.cpp b/modules/flash/producer/FlashAxContainer.cpp
new file mode 100644 (file)
index 0000000..cca013e
--- /dev/null
@@ -0,0 +1,926 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "FlashAxContainer.h"\r
+#include "../interop/TimerHelper.h"\r
+\r
+#include <common/log/log.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push, 2) // TODO\r
+#endif\r
+\r
+using namespace ATL;\r
+\r
+namespace caspar { namespace flash {\r
+\r
+CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}"));\r
+\r
+_ATL_FUNC_INFO fnInfoFlashCallEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };\r
+_ATL_FUNC_INFO fnInfoReadyStateChangeEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };\r
+\r
+FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), pTimerHelper(0), bInvalidRect_(false), bReadyToRender_(false), bHasNewTiming_(false), m_lpDD4(0), timerCount_(0), bIsEmpty_(false)\r
+{\r
+}\r
+FlashAxContainer::~FlashAxContainer()\r
+{      \r
+       if(m_lpDD4)\r
+       {\r
+               m_lpDD4->Release();\r
+               m_lpDD4 = nullptr;\r
+       }\r
+\r
+       if(pTimerHelper != 0)\r
+               delete pTimerHelper;\r
+}\r
+\r
+\r
+///////////////////\r
+// IObjectWithSite\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SetSite(IUnknown* pUnkSite)\r
+{\r
+       ATLTRACE(_T("IObjectWithSite::SetSite\n"));\r
+       HRESULT hr = IObjectWithSiteImpl<FlashAxContainer>::SetSite(pUnkSite);\r
+\r
+       if (SUCCEEDED(hr) && m_spUnkSite)\r
+       {\r
+               // Look for "outer" IServiceProvider\r
+               hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices);\r
+               ATLASSERT( !hr && _T("No ServiceProvider!") );\r
+       }\r
+\r
+       if (pUnkSite == NULL)\r
+               m_spServices.Release();\r
+\r
+       return hr;\r
+}\r
+\r
+///////////////////\r
+// IOleClientSite\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SaveObject()\r
+{\r
+       ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject"));\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)\r
+{\r
+/*     if(*ppmk != NULL) {\r
+               if(m_spMyMoniker == NULL) {\r
+                       ATL::CComObject<MyMoniker>* pMoniker = NULL;\r
+                       HRESULT hr = ATL::CComObject<MyMoniker>::CreateInstance(&pMoniker);\r
+                       if(SUCCEEDED(hr))\r
+                               m_spMyMoniker = pMoniker;\r
+               }\r
+\r
+               if(m_spMyMoniker != NULL) {\r
+                       *ppmk = m_spMyMoniker;\r
+                       (*ppmk)->AddRef();\r
+                       return S_OK;\r
+               }\r
+       }\r
+*/     if(ppmk != NULL)\r
+               *ppmk = NULL;\r
+       return E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetContainer(IOleContainer** ppContainer)\r
+{\r
+       ATLTRACE(_T("IOleClientSite::GetContainer\n"));\r
+       (*ppContainer) = NULL;\r
+       return E_NOINTERFACE;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowObject()\r
+{\r
+       ATLTRACE(_T("IOleClientSite::ShowObject\n"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnShowWindow(BOOL fShow)\r
+{\r
+       ATLTRACE(_T("IOleClientSite::OnShowWindow"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestNewObjectLayout()\r
+{\r
+       ATLTRACE(_T("IOleClientSite::RequestNewObjectLayout"));\r
+       return S_OK;\r
+}\r
+\r
+///////////////////\r
+// IOleInPlaceSite\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindow(HWND* pHwnd)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::GetWindow\n"));\r
+       (*pHwnd) = NULL;//GetApplication()->GetMainWindow()->getHwnd();\r
+       return E_FAIL;\r
+}\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::ContextSensitiveHelp(BOOL fEnterMode)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::ContextSensitiveHelp"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::CanInPlaceActivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::CanInPlaceActivate\n"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::OnInPlaceActivate"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIActivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::OnUIActivate\n"));\r
+       bUIActive_ = TRUE;\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::GetWindowContext\n"));\r
+       if (ppFrame != NULL)\r
+               *ppFrame = NULL;\r
+       if (ppDoc != NULL)\r
+               *ppDoc = NULL;\r
+\r
+       if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL)\r
+               return E_POINTER;\r
+\r
+       pFrameInfo->fMDIApp = FALSE;\r
+       pFrameInfo->haccel = NULL;\r
+       pFrameInfo->cAccelEntries = 0;\r
+       pFrameInfo->hwndFrame = NULL;\r
+\r
+       lprcPosRect->top = m_rcPos.top;\r
+       lprcPosRect->left = m_rcPos.left;\r
+       lprcPosRect->right = m_rcPos.right;\r
+       lprcPosRect->bottom = m_rcPos.bottom;\r
+\r
+       lprcClipRect->top = m_rcPos.top;\r
+       lprcClipRect->left = m_rcPos.left;\r
+       lprcClipRect->right = m_rcPos.right;\r
+       lprcClipRect->bottom = m_rcPos.bottom;\r
+\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Scroll(SIZE scrollExtant)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::Scroll"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIDeactivate(BOOL fUndoable)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::OnUIDeactivate\n"));\r
+       bUIActive_ = FALSE;\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::OnInPlaceDeactivate\n"));\r
+       bInPlaceActive_ = FALSE;\r
+       m_spInPlaceObjectWindowless.Release();\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::DiscardUndoState()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::DiscardUndoState"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::DeactivateAndUndo()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::DeactivateAndUndo"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnPosRectChange(LPCRECT lprcPosRect)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSite::OnPosRectChange"));\r
+       return S_OK;\r
+}\r
+\r
+\r
+/////////////////////\r
+// IOleInPlaceSiteEx\r
+/////////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)\r
+{\r
+       // should only be called once the first time control is inplace-activated\r
+       ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceActivateEx\n"));\r
+       ATLASSERT(bInPlaceActive_ == FALSE);\r
+       ATLASSERT(m_spInPlaceObjectWindowless == NULL);\r
+\r
+       bInPlaceActive_ = TRUE;\r
+       OleLockRunning(m_spOleObject, TRUE, FALSE);\r
+       HRESULT hr = E_FAIL;\r
+       if (dwFlags & ACTIVATE_WINDOWLESS)\r
+       {\r
+               hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless);\r
+\r
+               if (m_spInPlaceObjectWindowless != NULL)\r
+                       m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
+       }\r
+\r
+       return (m_spInPlaceObjectWindowless != NULL) ? S_OK : E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivateEx(BOOL fNoRedraw)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceDeactivateEx\n"));\r
+       bInPlaceActive_ = FALSE;\r
+       m_spInPlaceObjectWindowless.Release();\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestUIActivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteEx::RequestUIActivate\n"));\r
+       return S_OK;\r
+}\r
+\r
+\r
+/////////////////////////////\r
+// IOleInPlaceSiteWindowless\r
+/////////////////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::CanWindowlessActivate()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::CanWindowlessActivate\n"));\r
+       return S_OK;\r
+//     return S_FALSE;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetCapture()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::GetCapture\n"));\r
+       return bCapture_ ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SetCapture(BOOL fCapture)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::SetCapture\n"));\r
+       bCapture_ = fCapture;\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetFocus()\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::GetFocus\n"));\r
+       return bHaveFocus_ ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SetFocus(BOOL fGotFocus)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::SetFocus\n"));\r
+       bHaveFocus_ = fGotFocus;\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::GetDC"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::ReleaseDC(HDC hDC)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::ReleaseDC"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRect(LPCRECT pRect, BOOL fErase)\r
+{\r
+//     ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRect\n"));\r
+       \r
+       bInvalidRect_ = true;\r
+\r
+/*     //Keep a list of dirty rectangles in order to be able to redraw only them\r
+       if(pRect != NULL) {\r
+               bDirtyRects_.push_back(DirtyRect(*pRect, fErase != 0));\r
+       }\r
+       else {\r
+               bDirtyRects_.push_back(DirtyRect(true));\r
+       }\r
+*/     return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRgn(HRGN hRGN, BOOL fErase)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRng\n"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::ScrollRect"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::AdjustRect(LPRECT prc)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::AdjustRect"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)\r
+{\r
+       ATLTRACE(_T("IOleInPlaceSiteWindowless::OnDefWindowMessage"));\r
+       return S_OK;\r
+}\r
+\r
+///////////////////\r
+// IOleControlSite\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnControlInfoChanged()\r
+{\r
+       ATLTRACE(_T("IOleControlSite::OnControlInfoChanged"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::LockInPlaceActive(BOOL fLock)\r
+{\r
+       ATLTRACE(_T("IOleControlSite::LockInPlaceActive"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetExtendedControl(IDispatch** ppDisp)\r
+{\r
+       ATLTRACE(_T("IOleControlSite::GetExtendedControl"));\r
+\r
+       if (ppDisp == NULL)\r
+               return E_POINTER;\r
+       return m_spOleObject.QueryInterface(ppDisp);\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)\r
+{\r
+       ATLTRACE(_T("IOleControlSite::TransformCoords"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)\r
+{\r
+       ATLTRACE(_T("IOleControlSite::TranslateAccelerator"));\r
+       return S_FALSE;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::OnFocus(BOOL fGotFocus)\r
+{\r
+       bHaveFocus_ = fGotFocus;\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()\r
+{\r
+       ATLTRACE(_T("IOleControlSite::ShowPropertyFrame"));\r
+       return S_OK;\r
+}\r
+\r
+\r
+///////////////////\r
+// IAdviseSink\r
+///////////////////\r
+void STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnDataChange\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnViewChange\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk)\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnRename\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnSave()\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnSave\n"));\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnClose()\r
+{\r
+       ATLTRACE(_T("IAdviseSink::OnClose\n"));\r
+}\r
+\r
+\r
+//DirectDraw GUIDS\r
+\r
+DEFINE_GUID2(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35);\r
+DEFINE_GUID2(CLSID_DirectDraw7,0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5);\r
+\r
+DEFINE_GUID2(IID_IDirectDraw,0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);\r
+DEFINE_GUID2(IID_IDirectDraw3,0x618f8ad4,0x8b7a,0x11d0,0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d);\r
+DEFINE_GUID2(IID_IDirectDraw4,0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5);\r
+DEFINE_GUID2(IID_IDirectDraw7,0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b);\r
+\r
+///////////////////\r
+// IServiceProvider\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID riid, void** ppvObj) \r
+{\r
+//     ATLTRACE(_T("IServiceProvider::QueryService\n"));\r
+       //the flashcontrol asks for an interface {618F8AD4-8B7A-11D0-8FCC-00C04FD9189D}, this is IID for a DirectDraw3 object\r
+\r
+       ATLASSERT(ppvObj != NULL);\r
+       if (ppvObj == NULL)\r
+               return E_POINTER;\r
+       *ppvObj = NULL;\r
+       \r
+       HRESULT hr;\r
+       // Author: Makarov Igor\r
+       // Transparent Flash Control in Plain C++ \r
+       // http://www.codeproject.com/KB/COM/flashcontrol.aspx \r
+       if (IsEqualGUID(rsid, IID_IDirectDraw3))\r
+       {\r
+               if (!m_lpDD4)\r
+               {\r
+                       m_lpDD4 = new IDirectDraw4Ptr;\r
+                       hr = m_lpDD4->CreateInstance(CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER); \r
+                       if (FAILED(hr))\r
+                       {\r
+                               delete m_lpDD4;\r
+                               m_lpDD4 = NULL;\r
+                               CASPAR_LOG(info) << print_() << " DirectDraw not installed. Running without DirectDraw.";\r
+                               return E_NOINTERFACE;\r
+                       }\r
+               }\r
+               if (m_lpDD4 && m_lpDD4->GetInterfacePtr())\r
+               {\r
+                       *ppvObj = m_lpDD4->GetInterfacePtr();\r
+                       m_lpDD4->AddRef();\r
+                       return S_OK;\r
+               }\r
+       }\r
+\r
+       //TODO: The fullscreen-consumer requires that ths does NOT return an ITimerService\r
+       hr = QueryInterface(riid, ppvObj);//E_NOINTERFACE;\r
+\r
+       return hr;\r
+}\r
+\r
+\r
+///////////////////\r
+// ITimerService\r
+///////////////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer *pReferenceTimer, ITimer **ppNewTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::CreateTimer\n"));\r
+       if(pTimerHelper != 0)\r
+       {\r
+               delete pTimerHelper;\r
+               pTimerHelper = 0;\r
+       }\r
+       pTimerHelper = new TimerHelper();\r
+       return QueryInterface(__uuidof(ITimer), (void**) ppNewTimer);\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer **ppTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::GetNamedTimer"));\r
+       if(ppTimer == NULL)\r
+               return E_POINTER;\r
+       else\r
+               *ppTimer = NULL;\r
+\r
+       return E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer *pReferenceTimer)\r
+{\r
+       ATLTRACE(_T("ITimerService::SetNamedTimerReference"));\r
+       return S_OK;\r
+}\r
+\r
+///////////\r
+// ITimer\r
+///////////\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie)\r
+{\r
+       ATLTRACE(_T("Timer::Advise\n"));\r
+\r
+       if(pdwCookie == 0)\r
+               return E_POINTER;\r
+\r
+       if(pTimerHelper != 0)\r
+       {\r
+               pTimerHelper->Setup(vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);\r
+               *pdwCookie = pTimerHelper->ID;\r
+               bHasNewTiming_ = true;\r
+\r
+               return S_OK;\r
+       }\r
+       else\r
+               return E_OUTOFMEMORY;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)\r
+{\r
+       ATLTRACE(_T("Timer::Unadvice\n"));\r
+       if(pTimerHelper != 0)\r
+       {\r
+               pTimerHelper->pTimerSink = 0;\r
+               return S_OK;\r
+       }\r
+       else\r
+               return E_FAIL;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)\r
+{\r
+       ATLTRACE(_T("Timer::Freeze\n"));\r
+       return S_OK;\r
+}\r
+\r
+HRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT *pvtime)\r
+{\r
+       ATLTRACE(_T("Timer::GetTime\n"));\r
+       if(pvtime == 0)\r
+               return E_POINTER;\r
+\r
+//     return E_NOTIMPL;\r
+       pvtime->lVal = 0;\r
+       return S_OK;\r
+}\r
+\r
+double FlashAxContainer::GetFPS() {\r
+       if(pTimerHelper != 0 && pTimerHelper->interval > 0)\r
+               return (1000.0 / static_cast<double>(pTimerHelper->interval));\r
+       \r
+       return 0.0;\r
+}\r
+\r
+bool FlashAxContainer::IsReadyToRender() const {\r
+       return bReadyToRender_;\r
+}\r
+\r
+void FlashAxContainer::EnterFullscreen()\r
+{\r
+       if(m_spInPlaceObjectWindowless != 0)\r
+       {\r
+               HRESULT result;\r
+               m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1), &result);\r
+               m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(1, 1), &result);\r
+       }\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)\r
+{\r
+       std::wstring str(request);\r
+       if(str.find(TEXT("DisplayedTemplate")) != std::wstring::npos)\r
+       {\r
+               ATLTRACE(_T("ShockwaveFlash::DisplayedTemplate\n"));\r
+               bReadyToRender_ = true;\r
+       }\r
+       else if(str.find(TEXT("OnCommand")) != std::wstring::npos) {\r
+               //this is how templatehost 1.8 reports that a command has been received\r
+               CASPAR_LOG(debug)  << print_()  << L" [command]      " << str;\r
+               bCallSuccessful_ = true;\r
+       }\r
+       else if(str.find(TEXT("Activity")) != std::wstring::npos)\r
+       {\r
+               CASPAR_LOG(debug) << print_() << L" [activity]     " << str;\r
+\r
+               //this is how templatehost 1.7 reports that a command has been received\r
+               if(str.find(TEXT("Command recieved")) != std::wstring::npos)\r
+                       bCallSuccessful_ = true;\r
+\r
+               /*if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
+                       std::wstring::size_type pos = str.find(TEXT('@'));\r
+                       if(pos != std::wstring::npos)\r
+                               pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
+               }*/\r
+       }\r
+       else if(str.find(TEXT("OnNotify")) != std::wstring::npos)\r
+       {\r
+               CASPAR_LOG(info) << print_() << L" [notification] " << str;\r
+\r
+               //if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
+               //      std::wstring::size_type pos = str.find(TEXT('@'));\r
+               //      if(pos != std::wstring::npos)\r
+               //              pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
+               //}\r
+       }\r
+       else if(str.find(TEXT("IsEmpty")) != std::wstring::npos)\r
+       {\r
+               CASPAR_LOG(trace) << print_() << L" Empty.";\r
+               ATLTRACE(_T("ShockwaveFlash::IsEmpty\n"));\r
+               bIsEmpty_ = true;\r
+       }\r
+       else if(str.find(TEXT("OnError")) != std::wstring::npos)\r
+       {\r
+               CASPAR_LOG(error) << print_() << L" [error]        " << str;\r
+       }\r
+       else if(str.find(TEXT("OnDebug")) != std::wstring::npos)\r
+       {\r
+               CASPAR_LOG(debug) << print_() << L" [debug]        " << str;\r
+       }\r
+       //else if(str.find(TEXT("OnTemplateDescription")) != std::wstring::npos)\r
+       //{\r
+       //      CASPAR_LOG(error) << print_() << L" TemplateDescription: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
+       //}\r
+       //else if(str.find(TEXT("OnGetInfo")) != std::wstring::npos)\r
+       //{\r
+       //      CASPAR_LOG(error) << print_() << L" Info: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
+       //}\r
+       //else\r
+       //{\r
+       //      CASPAR_LOG(error) << print_() << L" Unknown: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
+       //}\r
+\r
+       CComPtr<IShockwaveFlash> spFlash;\r
+       HRESULT hr = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);\r
+       if(hr == S_OK && spFlash)\r
+       {\r
+               hr = spFlash->SetReturnValue(TEXT("<null/>"));\r
+       }\r
+}\r
+\r
+void STDMETHODCALLTYPE FlashAxContainer::OnReadyStateChange(long newState)\r
+{\r
+       if(newState == 4)\r
+       {\r
+               bReadyToRender_ = true;\r
+       }\r
+       else\r
+               bReadyToRender_ = false;\r
+}\r
+\r
+void FlashAxContainer::DestroyAxControl()\r
+{\r
+       GetControllingUnknown()->AddRef();\r
+\r
+       if ((!m_spViewObject) == false)\r
+               m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);\r
+\r
+       if ((!m_spOleObject) == false)\r
+       {\r
+               DispEventUnadvise(m_spOleObject, &DIID__IShockwaveFlashEvents);\r
+               m_spOleObject->Unadvise(m_dwOleObject);\r
+               m_spOleObject->Close(OLECLOSE_NOSAVE);\r
+               m_spOleObject->SetClientSite(NULL);\r
+       }\r
+\r
+       if ((!m_spUnknown) == false)\r
+       {\r
+               CComPtr<IObjectWithSite> spSite;\r
+               m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\r
+               if (spSite != NULL)\r
+                       spSite->SetSite(NULL);\r
+       }\r
+\r
+       if ((!m_spViewObject) == false)\r
+               m_spViewObject.Release();\r
+\r
+       if ((!m_spInPlaceObjectWindowless) == false)\r
+               m_spInPlaceObjectWindowless.Release();\r
+\r
+       if ((!m_spOleObject) == false)\r
+               m_spOleObject.Release();\r
+\r
+       if ((!m_spUnknown) == false)\r
+               m_spUnknown.Release();\r
+}\r
+\r
+bool FlashAxContainer::CheckForFlashSupport()\r
+{\r
+       CLSID clsid;\r
+       return SUCCEEDED(CLSIDFromString((LPOLESTR)flashGUID_, &clsid));\r
+}\r
+\r
+HRESULT FlashAxContainer::CreateAxControl()\r
+{\r
+       CLSID clsid;\r
+       HRESULT hr = CLSIDFromString((LPOLESTR)flashGUID_, &clsid); \r
+       if(SUCCEEDED(hr))\r
+               hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), (void**)&m_spUnknown);\r
+\r
+//Start ActivateAx\r
+       if(SUCCEEDED(hr))\r
+       {\r
+               m_spUnknown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);\r
+               if(m_spOleObject)\r
+               {\r
+                       m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);\r
+                       if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)\r
+                       {\r
+                               CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                               m_spOleObject->SetClientSite(spClientSite);\r
+                       }\r
+\r
+                       //Initialize control\r
+                       CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);\r
+                       if (spPSI)\r
+                               hr = spPSI->InitNew();\r
+\r
+                       if (FAILED(hr)) // If the initialization of the control failed...\r
+                       {\r
+                               // Clean up and return\r
+                               if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)\r
+                                       m_spOleObject->SetClientSite(NULL);\r
+\r
+                               m_dwMiscStatus = 0;\r
+                               m_spOleObject.Release();\r
+                               m_spUnknown.Release();\r
+\r
+                               return hr;\r
+                       }\r
+                       //end Initialize object\r
+\r
+                       if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))\r
+                       {\r
+                               CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                               m_spOleObject->SetClientSite(spClientSite);\r
+                       }\r
+\r
+                       CComPtr<IShockwaveFlash> spFlash;\r
+                       HRESULT hResultQuality;\r
+                       HRESULT hr2 = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);\r
+                       if(hr2 == S_OK && spFlash)\r
+                       {\r
+                               if(FAILED(spFlash->put_WMode(TEXT("Transparent"))))\r
+                                       CASPAR_LOG(warning) << print_() << L" Failed to set flash container to transparent mode.";\r
+                               //spFlash->put_WMode(TEXT("GPU"));\r
+                               hResultQuality = spFlash->put_Quality2(TEXT("Best"));\r
+                       }\r
+                       if(SUCCEEDED(DispEventAdvise(spFlash, &DIID__IShockwaveFlashEvents)))\r
+                       {\r
+                       }\r
+\r
+                       HRESULT hrView = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);\r
+\r
+                       CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());\r
+                       m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);\r
+                       if (m_spViewObject)\r
+                               m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);\r
+\r
+                       if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0)\r
+                       {\r
+                               //Initialize window to some dummy size\r
+                               m_rcPos.top = 0;\r
+                               m_rcPos.left = 0;\r
+                               m_rcPos.right = 720;\r
+                               m_rcPos.bottom = 576;\r
+\r
+                               m_pxSize.cx = m_rcPos.right - m_rcPos.left;\r
+                               m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\r
+                               AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\r
+                               m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+                               m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+                               AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\r
+                               m_rcPos.right = m_rcPos.left + m_pxSize.cx;\r
+                               m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\r
+\r
+                               CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                               hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);\r
+                       }\r
+               }\r
+               CComPtr<IObjectWithSite> spSite;\r
+               m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\r
+               if (spSite != NULL)\r
+                       spSite->SetSite(GetControllingUnknown());\r
+       }\r
+//End ActivateAx\r
+\r
+//     hr = E_FAIL;\r
+       if (FAILED(hr) || m_spUnknown == NULL)\r
+       {\r
+               return E_FAIL;\r
+               // We don't have a control or something failed so release\r
+//             ReleaseAll();\r
+       }\r
+\r
+       return S_OK;\r
+}\r
+\r
+void FlashAxContainer::SetSize(size_t width, size_t height) {\r
+       if(m_spInPlaceObjectWindowless != 0)\r
+       {\r
+               m_rcPos.top = 0;\r
+               m_rcPos.left = 0;\r
+               m_rcPos.right = width;\r
+               m_rcPos.bottom = height;\r
+\r
+               m_pxSize.cx = m_rcPos.right - m_rcPos.left;\r
+               m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\r
+               AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\r
+               m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+               m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+               AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\r
+               m_rcPos.right = m_rcPos.left + m_pxSize.cx;\r
+               m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\r
+\r
+               m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
+               bInvalidRect_ = true;\r
+       }\r
+}\r
+\r
+HRESULT FlashAxContainer::QueryControl(REFIID iid, void** ppUnk)\r
+{\r
+       ATLASSERT(ppUnk != NULL);\r
+       if (ppUnk == NULL)\r
+               return E_POINTER;\r
+       HRESULT hr;\r
+       hr = m_spOleObject->QueryInterface(iid, ppUnk);\r
+       return hr;\r
+}\r
+\r
+bool FlashAxContainer::DrawControl(HDC targetDC)\r
+{\r
+//     ATLTRACE(_T("FlashAxContainer::DrawControl\n"));\r
+       DVASPECTINFO aspectInfo = {sizeof(DVASPECTINFO), DVASPECTINFOFLAG_CANOPTIMIZE};\r
+       HRESULT hr = S_OK;\r
+\r
+       hr = m_spViewObject->Draw(DVASPECT_CONTENT, -1, &aspectInfo, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
+       bInvalidRect_ = false;\r
+/*     const video_format_desc& fmtDesc = video_format_desc::FormatDescriptions[format_];\r
+\r
+       //Trying to redraw just the dirty rectangles. Doesn't seem to work when the movie uses "filters", such as glow, dropshadow etc.\r
+       std::vector<flash::DirtyRect>::iterator it = bDirtyRects_.begin();\r
+       std::vector<flash::DirtyRect>::iterator end = bDirtyRects_.end();\r
+       for(; it != end; ++it) {\r
+               flash::DirtyRect& dirtyRect = (*it);\r
+               if(dirtyRect.bWhole || dirtyRect.rect.right >= fmtDesc.width || dirtyRect.rect.bottom >= fmtDesc.height) {\r
+                       m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
+                       hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
+                       break;\r
+               }\r
+               else {\r
+                       m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &(dirtyRect.rect));\r
+                       hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
+               }\r
+       }\r
+       bDirtyRects_.clear();\r
+*/\r
+\r
+       return (hr == S_OK);\r
+}\r
+\r
+void FlashAxContainer::Tick()\r
+{\r
+       if(pTimerHelper)\r
+       {\r
+               DWORD time = pTimerHelper->Invoke(); // Tick flash\r
+               if(time - timerCount_ >= 400)\r
+               {\r
+                       timerCount_ = time;\r
+                       HRESULT hr;\r
+                       m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);\r
+               }\r
+       }\r
+}\r
+\r
+bool FlashAxContainer::FlashCall(const std::wstring& str, std::wstring& result2)\r
+{\r
+       CComBSTR result;\r
+       CComPtr<IShockwaveFlash> spFlash;\r
+       QueryControl(&spFlash);\r
+       CComBSTR request(str.c_str());\r
+       \r
+       bIsEmpty_ = false;\r
+       bCallSuccessful_ = false;\r
+       for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)\r
+               spFlash->CallFunction(request, &result);\r
+\r
+       if(bCallSuccessful_)\r
+               result2 = result;\r
+\r
+       return bCallSuccessful_;\r
+}\r
+\r
+}      //namespace flash\r
+}      //namespace caspar
\ No newline at end of file
diff --git a/modules/flash/producer/FlashAxContainer.h b/modules/flash/producer/FlashAxContainer.h
new file mode 100644 (file)
index 0000000..e5663e0
--- /dev/null
@@ -0,0 +1,307 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
\r
+#ifndef _FLASHAXCONTAINER_H__\r
+#define _FLASHAXCONTAINER_H__\r
+\r
+#pragma once\r
+\r
+#include <atlbase.h>\r
+#include <atlcom.h>\r
+#include <atlhost.h>\r
+#include <ocmm.h>\r
+\r
+#include <functional>\r
+#include <vector>\r
+\r
+#include <core/video_format.h>\r
+#include "../interop/axflash.h"\r
+//#import "progid:ShockwaveFlash.ShockwaveFlash.9" no_namespace, named_guids\r
+\r
+#include <comdef.h>\r
+\r
+#include "../interop/TimerHelper.h"\r
+\r
+#include <InitGuid.h>\r
+#include <ddraw.h>\r
+\r
+#ifndef DEFINE_GUID2\r
+#define DEFINE_GUID2(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
+               const GUID name \\r
+                               = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }\r
+#endif    \r
+\r
+_COM_SMARTPTR_TYPEDEF(IDirectDraw4, IID_IDirectDraw4);\r
+\r
+namespace caspar {\r
+\r
+namespace flash {\r
+\r
+class TimerHelper;\r
+struct DirtyRect {\r
+       DirtyRect(LONG l, LONG t, LONG r, LONG b, bool e) : bErase(e), bWhole(false) { \r
+               rect.left = l;\r
+               rect.top = t;\r
+               rect.right = r;\r
+               rect.bottom = b; \r
+       }\r
+       DirtyRect(const RECT& rc, bool e) : bErase(e), bWhole(false)  {\r
+               rect.left = rc.left;\r
+               rect.top = rc.top;\r
+               rect.right = rc.right;\r
+               rect.bottom = rc.bottom; \r
+       }\r
+       explicit DirtyRect(bool b) : bWhole(b) {}\r
+\r
+       RECT    rect;\r
+       bool    bErase;\r
+       bool    bWhole;\r
+};\r
+\r
+extern _ATL_FUNC_INFO fnInfoFlashCallEvent;\r
+extern _ATL_FUNC_INFO fnInfoReadyStateChangeEvent;\r
+\r
+class ATL_NO_VTABLE FlashAxContainer : \r
+               public ATL::CComCoClass<FlashAxContainer , &CLSID_NULL>,\r
+               public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,\r
+               public IOleClientSite,\r
+               public IOleContainer,\r
+               public IOleControlSite,\r
+               public IOleInPlaceSiteWindowless,\r
+               public IObjectWithSiteImpl<FlashAxContainer>,\r
+               public IServiceProvider,\r
+               public IAdviseSink,\r
+               public ITimerService,\r
+               public ITimer,\r
+               public IDispatchImpl<IDispatch>,\r
+               public IDispEventSimpleImpl<0, FlashAxContainer, &DIID__IShockwaveFlashEvents>\r
+{\r
+\r
+public:\r
+\r
+       FlashAxContainer();\r
+       virtual ~FlashAxContainer();\r
+\r
+       DECLARE_NO_REGISTRY()\r
+       DECLARE_POLY_AGGREGATABLE(FlashAxContainer)\r
+       DECLARE_GET_CONTROLLING_UNKNOWN()\r
+\r
+       BEGIN_COM_MAP(FlashAxContainer)\r
+               COM_INTERFACE_ENTRY(IDispatch)\r
+               COM_INTERFACE_ENTRY(IOleClientSite)\r
+               COM_INTERFACE_ENTRY(IObjectWithSite)\r
+               COM_INTERFACE_ENTRY(IOleControlSite)\r
+               COM_INTERFACE_ENTRY(IOleContainer)\r
+\r
+               COM_INTERFACE_ENTRY(IOleInPlaceSiteWindowless)\r
+               COM_INTERFACE_ENTRY(IOleInPlaceSiteEx)\r
+               COM_INTERFACE_ENTRY(IOleInPlaceSite)\r
+               COM_INTERFACE_ENTRY(IOleWindow)\r
+\r
+               COM_INTERFACE_ENTRY(IServiceProvider)\r
+\r
+               COM_INTERFACE_ENTRY(IAdviseSink)\r
+\r
+               COM_INTERFACE_ENTRY(ITimerService)\r
+\r
+               COM_INTERFACE_ENTRY(ITimer)\r
+       END_COM_MAP()\r
+\r
+       BEGIN_SINK_MAP(FlashAxContainer)\r
+               SINK_ENTRY_INFO(0, DIID__IShockwaveFlashEvents, 0xc5, OnFlashCall, &fnInfoFlashCallEvent)\r
+               SINK_ENTRY_INFO(0, DIID__IShockwaveFlashEvents, 0xfffffd9f, OnReadyStateChange, &fnInfoReadyStateChangeEvent)\r
+       END_SINK_MAP()\r
+\r
+       void STDMETHODCALLTYPE OnFlashCall(BSTR request);\r
+       void STDMETHODCALLTYPE OnReadyStateChange(long newState);\r
+\r
+// IObjectWithSite\r
+       STDMETHOD(SetSite)(IUnknown* pUnkSite);\r
+\r
+// IOleClientSite\r
+       STDMETHOD(SaveObject)();\r
+       STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk);\r
+       STDMETHOD(GetContainer)(IOleContainer** ppContainer);\r
+       STDMETHOD(ShowObject)();\r
+       STDMETHOD(OnShowWindow)(BOOL fShow);\r
+       STDMETHOD(RequestNewObjectLayout)();\r
+\r
+// IOleInPlaceSite\r
+       STDMETHOD(GetWindow)(HWND* pHwnd);\r
+       STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);\r
+       STDMETHOD(CanInPlaceActivate)();\r
+       STDMETHOD(OnInPlaceActivate)();\r
+       STDMETHOD(OnInPlaceDeactivate)();\r
+       STDMETHOD(OnUIActivate)();\r
+       STDMETHOD(OnUIDeactivate)(BOOL fUndoable);\r
+       STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo);\r
+       STDMETHOD(Scroll)(SIZE scrollExtant);\r
+       STDMETHOD(DiscardUndoState)();\r
+       STDMETHOD(DeactivateAndUndo)();\r
+       STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);\r
+\r
+// IOleInPlaceSiteEx\r
+       STDMETHOD(OnInPlaceActivateEx)(BOOL* pfNoRedraw, DWORD dwFlags);\r
+       STDMETHOD(OnInPlaceDeactivateEx)(BOOL fNoRedraw);\r
+       STDMETHOD(RequestUIActivate)();\r
+\r
+// IOleInPlaceSiteWindowless\r
+       STDMETHOD(CanWindowlessActivate)();\r
+       STDMETHOD(GetCapture)();\r
+       STDMETHOD(SetCapture)(BOOL fCapture);\r
+       STDMETHOD(GetFocus)();\r
+       STDMETHOD(SetFocus)(BOOL fGotFocus);\r
+       STDMETHOD(GetDC)(LPCRECT pRect, DWORD grfFlags, HDC* phDC);\r
+       STDMETHOD(ReleaseDC)(HDC hDC);\r
+       STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase);\r
+       STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase);\r
+       STDMETHOD(ScrollRect)(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip);\r
+       STDMETHOD(AdjustRect)(LPRECT prc);\r
+       STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult);\r
+\r
+// IOleControlSite\r
+       STDMETHOD(OnControlInfoChanged)();\r
+       STDMETHOD(LockInPlaceActive)(BOOL fLock);\r
+       STDMETHOD(GetExtendedControl)(IDispatch** ppDisp);\r
+       STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags);\r
+       STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, DWORD grfModifiers);\r
+       STDMETHOD(OnFocus)(BOOL fGotFocus);\r
+       STDMETHOD(ShowPropertyFrame)();\r
+\r
+// IAdviseSink\r
+       STDMETHOD_(void, OnDataChange)(FORMATETC* pFormatetc, STGMEDIUM* pStgmed);\r
+       STDMETHOD_(void, OnViewChange)(DWORD dwAspect, LONG lindex);\r
+       STDMETHOD_(void, OnRename)(IMoniker* pmk);\r
+       STDMETHOD_(void, OnSave)();\r
+       STDMETHOD_(void, OnClose)();\r
+\r
+// IServiceProvider\r
+       STDMETHOD(QueryService)( REFGUID rsid, REFIID riid, void** ppvObj);\r
+\r
+// IOleContainer\r
+       STDMETHOD(ParseDisplayName)(IBindCtx*, LPOLESTR, ULONG*, IMoniker**)\r
+       {\r
+               ATLTRACENOTIMPL(_T("IOleContainer::ParseDisplayName"));\r
+       }\r
+       STDMETHOD(EnumObjects)(DWORD, IEnumUnknown** ppenum)\r
+       {\r
+               if (ppenum == NULL)\r
+                       return E_POINTER;\r
+               *ppenum = NULL;\r
+               typedef CComObject<CComEnum<IEnumUnknown, &__uuidof(IEnumUnknown), IUnknown*, _CopyInterface<IUnknown> > > enumunk;\r
+               enumunk* p = NULL;\r
+               ATLTRY(p = new enumunk);\r
+               if(p == NULL)\r
+                       return E_OUTOFMEMORY;\r
+               IUnknown* pTemp = m_spUnknown;\r
+               // There is always only one object.\r
+               HRESULT hRes = p->Init(reinterpret_cast<IUnknown**>(&pTemp), reinterpret_cast<IUnknown**>(&pTemp + 1), GetControllingUnknown(), AtlFlagCopy);\r
+               if (SUCCEEDED(hRes))\r
+                       hRes = p->QueryInterface(__uuidof(IEnumUnknown), (void**)ppenum);\r
+               if (FAILED(hRes))\r
+                       delete p;\r
+               return hRes;\r
+       }\r
+       STDMETHOD(LockContainer)(BOOL)\r
+       {\r
+               ATLTRACENOTIMPL(_T("IOleContainer::LockContainer"));\r
+       }\r
+\r
+//ITimerService\r
+       STDMETHOD(CreateTimer)(ITimer *pReferenceTimer, ITimer **ppNewTimer);\r
+       STDMETHOD(GetNamedTimer)(REFGUID rguidName, ITimer **ppTimer);\r
+       STDMETHOD(SetNamedTimerReference)(REFGUID rguidName, ITimer *pReferenceTimer);\r
+\r
+//ITimer\r
+       STDMETHOD(Advise)(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie);\r
+       STDMETHOD(Unadvise)(DWORD dwCookie);\r
+       STDMETHOD(Freeze)(BOOL fFreeze);\r
+       STDMETHOD(GetTime)(VARIANT *pvtime);\r
+       double GetFPS();\r
+\r
+       void set_print(const std::function<std::wstring()>& print) { print_ = print;}\r
+\r
+       HRESULT CreateAxControl();\r
+       void DestroyAxControl();\r
+       HRESULT QueryControl(REFIID iid, void** ppUnk);\r
+\r
+       template <class Q>\r
+       HRESULT QueryControl(Q** ppUnk)\r
+       {\r
+               return QueryControl(__uuidof(Q), (void**)ppUnk);\r
+       }\r
+\r
+//     static ATL::CComObject<FlashAxContainer>* CreateInstance();\r
+\r
+       void Tick();\r
+       bool FlashCall(const std::wstring& str, std::wstring& result);\r
+       bool DrawControl(HDC targetDC);\r
+       bool InvalidRect() const { return bInvalidRect_; } \r
+       bool IsEmpty() const { return bIsEmpty_; }\r
+\r
+       void SetSize(size_t width, size_t height);\r
+       bool IsReadyToRender() const;\r
+       void EnterFullscreen();\r
+\r
+       static bool CheckForFlashSupport();\r
+\r
+       ATL::CComPtr<IOleInPlaceObjectWindowless> m_spInPlaceObjectWindowless;\r
+\r
+private:\r
+       std::function<std::wstring()> print_;\r
+       TimerHelper* pTimerHelper;\r
+       volatile bool bInvalidRect_;\r
+       volatile bool bCallSuccessful_;\r
+       volatile bool bReadyToRender_;\r
+       volatile bool bIsEmpty_;\r
+       volatile bool bHasNewTiming_;\r
+       std::vector<DirtyRect> bDirtyRects_;\r
+\r
+\r
+       IDirectDraw4Ptr *m_lpDD4;\r
+       static CComBSTR flashGUID_;\r
+\r
+       DWORD timerCount_;\r
+\r
+//     state\r
+       bool            bUIActive_;\r
+       bool            bInPlaceActive_;\r
+       unsigned long           bHaveFocus_ : 1;\r
+       unsigned long           bCapture_ : 1;\r
+\r
+       DWORD m_dwOleObject;\r
+       DWORD m_dwMiscStatus;\r
+       SIZEL m_hmSize;\r
+       SIZEL m_pxSize;\r
+       RECT m_rcPos;\r
+\r
+       ATL::CComPtr<IUnknown> m_spUnknown;\r
+       ATL::CComPtr<IOleObject> m_spServices;\r
+       ATL::CComPtr<IOleObject> m_spOleObject;\r
+       ATL::CComPtr<IViewObjectEx> m_spViewObject;\r
+\r
+//     ATL::CComPtr<ATL::CComObject<MyMoniker> > m_spMyMoniker;\r
+};\r
+\r
+}      //namespace flash\r
+}      //namespace caspar\r
+\r
+#endif //_FLASHAXCONTAINER_H__
\ No newline at end of file
diff --git a/modules/flash/producer/cg_producer.cpp b/modules/flash/producer/cg_producer.cpp
new file mode 100644 (file)
index 0000000..e49cf2f
--- /dev/null
@@ -0,0 +1,267 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "cg_producer.h"\r
+\r
+#include "flash_producer.h"\r
+\r
+#include <common/env.h>\r
+\r
+#include <core/mixer/mixer.h>\r
+\r
+#include <boost/filesystem.hpp>\r
+#include <boost/format.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/regex.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+               \r
+namespace caspar { namespace flash {\r
+       \r
+struct cg_producer::implementation : boost::noncopyable\r
+{\r
+       safe_ptr<core::frame_producer> flash_producer_;\r
+public:\r
+       implementation(const safe_ptr<core::frame_producer>& frame_producer) \r
+               : flash_producer_(frame_producer)\r
+       {}\r
+       \r
+       boost::unique_future<std::wstring> add(int layer, std::wstring filename,  bool play_on_load, const std::wstring& label, const std::wstring& data)\r
+       {\r
+               if(filename.size() > 0 && filename[0] == L'/')\r
+                       filename = filename.substr(1, filename.size()-1);\r
+\r
+               if(boost::filesystem::wpath(filename).extension() == L"")\r
+                       filename += L".ft";\r
+               \r
+               auto str = (boost::wformat(L"<invoke name=\"Add\" returntype=\"xml\"><arguments><number>%1%</number><string>%2%</string>%3%<string>%4%</string><string><![CDATA[%5%]]></string></arguments></invoke>") % layer % filename % (play_on_load?TEXT("<true/>"):TEXT("<false/>")) % label % data).str();\r
+\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking add-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> remove(int layer)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"Delete\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking remove-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> play(int layer)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"Play\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking play-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> stop(int layer, unsigned int)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"Stop\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><number>0</number></arguments></invoke>") % layer).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking stop-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> next(int layer)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"Next\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking next-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> update(int layer, const std::wstring& data)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"SetData\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><string><![CDATA[%2%]]></string></arguments></invoke>") % layer % data).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() <<" Invoking update-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> invoke(int layer, const std::wstring& label)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"Invoke\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><string>%2%</string></arguments></invoke>") % layer % label).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking invoke-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> description(int layer)\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"GetDescription\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking description-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> template_host_info()\r
+       {\r
+               auto str = (boost::wformat(L"<invoke name=\"GetInfo\" returntype=\"xml\"><arguments></arguments></invoke>")).str();\r
+               CASPAR_LOG(info) << flash_producer_->print() << " Invoking info-command: " << str;\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       boost::unique_future<std::wstring> call(const std::wstring& str)\r
+       {               \r
+               static const boost::wregex add_exp                      (L"ADD (?<LAYER>\\d+) (?<FILENAME>[^\\s]+) (?<PLAY_ON_LOAD>\\d)( (?<DATA>.*))?");\r
+               static const boost::wregex remove_exp           (L"REMOVE (?<LAYER>\\d+)");\r
+               static const boost::wregex play_exp                     (L"PLAY (?<LAYER>\\d+)");\r
+               static const boost::wregex stop_exp                     (L"STOP (?<LAYER>\\d+)");\r
+               static const boost::wregex next_exp                     (L"NEXT (?<LAYER>\\d+)");\r
+               static const boost::wregex update_exp           (L"UPDATE (?<LAYER>\\d+) (?<DATA>.+)");\r
+               static const boost::wregex invoke_exp           (L"INVOKE (?<LAYER>\\d+) (?<LABEL>.+)");\r
+               static const boost::wregex description_exp      (L"INFO (?<LAYER>\\d+)");\r
+               static const boost::wregex info_exp                     (L"INFO");\r
+               \r
+               boost::wsmatch what;\r
+               if(boost::regex_match(str, what, add_exp))\r
+                       return add(boost::lexical_cast<int>(what["LAYER"].str()), flash::find_template(env::template_folder() + what["FILENAME"].str()), boost::lexical_cast<bool>(what["PLAY_ON_LOAD"].str()), L"", what["DATA"].str()); \r
+               else if(boost::regex_match(str, what, remove_exp))\r
+                       return remove(boost::lexical_cast<int>(what["LAYER"].str())); \r
+               else if(boost::regex_match(str, what, stop_exp))\r
+                       return stop(boost::lexical_cast<int>(what["LAYER"].str()), 0); \r
+               else if(boost::regex_match(str, what, next_exp))\r
+                       return next(boost::lexical_cast<int>(what["LAYER"].str())); \r
+               else if(boost::regex_match(str, what, update_exp))\r
+                       return update(boost::lexical_cast<int>(what["LAYER"].str()), what["DATA"].str()); \r
+               else if(boost::regex_match(str, what, next_exp))\r
+                       return invoke(boost::lexical_cast<int>(what["LAYER"].str()), what["LABEL"].str()); \r
+               else if(boost::regex_match(str, what, description_exp))\r
+                       return description(boost::lexical_cast<int>(what["LAYER"].str())); \r
+               else if(boost::regex_match(str, what, invoke_exp))\r
+                       return template_host_info(); \r
+\r
+               return flash_producer_->call(str);\r
+       }\r
+\r
+       safe_ptr<core::basic_frame> receive(int hints)\r
+       {\r
+               return flash_producer_->receive(hints);\r
+       }\r
+\r
+       safe_ptr<core::basic_frame> last_frame() const\r
+       {\r
+               return flash_producer_->last_frame();\r
+       }               \r
+                       \r
+       std::wstring print() const\r
+       {\r
+               return flash_producer_->print();\r
+       }\r
+\r
+       boost::property_tree::wptree info() const\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"cg-producer");\r
+               return info;\r
+       }\r
+\r
+       std::wstring timed_invoke(int layer, const std::wstring& label)\r
+       {\r
+               auto result = invoke(layer, label);\r
+               if(result.timed_wait(boost::posix_time::seconds(2)))\r
+                       return result.get();\r
+               return L"";\r
+       }\r
+       std::wstring timed_description(int layer)\r
+       {\r
+               auto result = description(layer);\r
+               if(result.timed_wait(boost::posix_time::seconds(2)))\r
+                       return result.get();\r
+               return L"";\r
+       }\r
+       std::wstring timed_template_host_info()\r
+       {\r
+               auto result = template_host_info();\r
+               if(result.timed_wait(boost::posix_time::seconds(2)))\r
+                       return result.get();\r
+               return L"";\r
+       }\r
+};\r
+       \r
+safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel>& video_channel, int render_layer)\r
+{      \r
+       auto flash_producer = video_channel->stage()->foreground(render_layer).get();\r
+\r
+       try\r
+       {\r
+               if(flash_producer->print().find(L"flash[") == std::string::npos) // UGLY hack\r
+               {\r
+                       flash_producer = flash::create_producer(video_channel->mixer(), boost::assign::list_of<std::wstring>());        \r
+                       video_channel->stage()->load(render_layer, flash_producer); \r
+                       video_channel->stage()->play(render_layer);\r
+               }\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               throw;\r
+       }\r
+\r
+       return make_safe<cg_producer>(flash_producer);\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_cg_producer_and_autoplay_file(\r
+               const safe_ptr<core::frame_factory>& frame_factory, \r
+               const std::vector<std::wstring>& params,\r
+               const std::wstring& filename) \r
+{\r
+       if(!boost::filesystem::exists(filename))\r
+               return core::frame_producer::empty();\r
+               \r
+       boost::filesystem2::wpath path(filename);\r
+       path = boost::filesystem2::complete(path);\r
+       auto filename2 = path.file_string();\r
+\r
+       auto flash_producer = flash::create_producer(frame_factory, boost::assign::list_of<std::wstring>());    \r
+       auto producer = make_safe<cg_producer>(flash_producer);\r
+       producer->add(0, filename2, 1);\r
+\r
+       return producer;\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_ct_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params) \r
+{\r
+       return create_cg_producer_and_autoplay_file(frame_factory, params, env::media_folder() + L"\\" + params[0] + L".ct");\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_cg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params) \r
+{\r
+       if(params.empty() || params.at(0) != L"[CG]")\r
+               return core::frame_producer::empty();\r
+\r
+       return make_safe<cg_producer>(flash::create_producer(frame_factory, boost::assign::list_of<std::wstring>()));   \r
+}\r
+\r
+cg_producer::cg_producer(const safe_ptr<core::frame_producer>& frame_producer) : impl_(new implementation(frame_producer)){}\r
+cg_producer::cg_producer(cg_producer&& other) : impl_(std::move(other.impl_)){}\r
+safe_ptr<core::basic_frame> cg_producer::receive(int hints){return impl_->receive(hints);}\r
+safe_ptr<core::basic_frame> cg_producer::last_frame() const{return impl_->last_frame();}\r
+void cg_producer::add(int layer, const std::wstring& template_name,  bool play_on_load, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, template_name, play_on_load, startFromLabel, data);}\r
+void cg_producer::remove(int layer){impl_->remove(layer);}\r
+void cg_producer::play(int layer){impl_->play(layer);}\r
+void cg_producer::stop(int layer, unsigned int mix_out_duration){impl_->stop(layer, mix_out_duration);}\r
+void cg_producer::next(int layer){impl_->next(layer);}\r
+void cg_producer::update(int layer, const std::wstring& data){impl_->update(layer, data);}\r
+std::wstring cg_producer::print() const{return impl_->print();}\r
+boost::unique_future<std::wstring> cg_producer::call(const std::wstring& str){return impl_->call(str);}\r
+std::wstring cg_producer::invoke(int layer, const std::wstring& label){return impl_->timed_invoke(layer, label);}\r
+std::wstring cg_producer::description(int layer){return impl_->timed_description(layer);}\r
+std::wstring cg_producer::template_host_info(){return impl_->timed_template_host_info();}\r
+boost::property_tree::wptree cg_producer::info() const{return impl_->info();}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/producer/cg_producer.h b/modules/flash/producer/cg_producer.h
new file mode 100644 (file)
index 0000000..875b3cf
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/producer/stage.h>\r
+#include <core/video_format.h>\r
+#include <core/video_channel.h>\r
+\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace flash {\r
+               \r
+class cg_producer : public core::frame_producer\r
+{\r
+public:\r
+       static const unsigned int DEFAULT_LAYER = 9999;\r
+\r
+       explicit cg_producer(const safe_ptr<core::frame_producer>& producer);\r
+       cg_producer(cg_producer&& other);\r
+       \r
+       // frame_producer\r
+\r
+       virtual safe_ptr<core::basic_frame> receive(int) override;\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override;\r
+       virtual std::wstring print() const override;\r
+       virtual boost::unique_future<std::wstring> call(const std::wstring&) override;\r
+       virtual boost::property_tree::wptree info() const override;\r
+\r
+       //cg_producer\r
+\r
+       void add(int layer, const std::wstring& template_name,  bool play_on_load, const std::wstring& start_from_label = TEXT(""), const std::wstring& data = TEXT(""));\r
+       void remove(int layer);\r
+       void play(int layer);\r
+       void stop(int layer, unsigned int mix_out_duration);\r
+       void next(int layer);\r
+       void update(int layer, const std::wstring& data);\r
+       std::wstring invoke(int layer, const std::wstring& label);\r
+       std::wstring description(int layer);\r
+       std::wstring template_host_info();\r
+\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel>& video_channel, int layer_index = cg_producer::DEFAULT_LAYER);\r
+\r
+safe_ptr<core::frame_producer> create_ct_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_cg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/producer/flash_producer.cpp b/modules/flash/producer/flash_producer.cpp
new file mode 100644 (file)
index 0000000..7afb1bd
--- /dev/null
@@ -0,0 +1,535 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4146)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+\r
+#include "flash_producer.h"\r
+#include "FlashAxContainer.h"\r
+\r
+#include "../util/swf.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/env.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/concurrency/lock.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/memory/memclr.h>\r
+#include <common/utility/timer.h>\r
+\r
+#include <boost/filesystem.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/timer.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+\r
+#include <functional>\r
+\r
+#include <tbb/spin_mutex.h>\r
+\r
+namespace caspar { namespace flash {\r
+               \r
+class bitmap\r
+{\r
+public:\r
+       bitmap(size_t width, size_t height)\r
+               : bmp_data_(nullptr)\r
+               , hdc_(CreateCompatibleDC(0), DeleteDC)\r
+       {       \r
+               BITMAPINFO info;\r
+               memset(&info, 0, sizeof(BITMAPINFO));\r
+               info.bmiHeader.biBitCount = 32;\r
+               info.bmiHeader.biCompression = BI_RGB;\r
+               info.bmiHeader.biHeight = -height;\r
+               info.bmiHeader.biPlanes = 1;\r
+               info.bmiHeader.biSize = sizeof(BITMAPINFO);\r
+               info.bmiHeader.biWidth = width;\r
+\r
+               bmp_.reset(CreateDIBSection(static_cast<HDC>(hdc_.get()), &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), 0, 0), DeleteObject);\r
+               SelectObject(static_cast<HDC>(hdc_.get()), bmp_.get()); \r
+\r
+               if(!bmp_data_)\r
+                       BOOST_THROW_EXCEPTION(std::bad_alloc());\r
+       }\r
+\r
+       operator HDC() {return static_cast<HDC>(hdc_.get());}\r
+\r
+       BYTE* data() { return bmp_data_;}\r
+       const BYTE* data() const { return bmp_data_;}\r
+\r
+private:\r
+       BYTE* bmp_data_;        \r
+       std::shared_ptr<void> hdc_;\r
+       std::shared_ptr<void> bmp_;\r
+};\r
+\r
+struct template_host\r
+{\r
+       std::wstring  video_mode;\r
+       std::wstring  filename;\r
+       size_t            width;\r
+       size_t            height;\r
+};\r
+\r
+template_host get_template_host(const core::video_format_desc& desc)\r
+{\r
+       try\r
+       {\r
+               std::vector<template_host> template_hosts;\r
+               BOOST_FOREACH(auto& xml_mapping, env::properties().get_child(L"configuration.template-hosts"))\r
+               {\r
+                       try\r
+                       {\r
+                               template_host template_host;\r
+                               template_host.video_mode                = xml_mapping.second.get(L"video-mode", L"");\r
+                               template_host.filename                  = xml_mapping.second.get(L"filename",   L"cg.fth");\r
+                               template_host.width                             = xml_mapping.second.get(L"width",              desc.width);\r
+                               template_host.height                    = xml_mapping.second.get(L"height",             desc.height);\r
+                               template_hosts.push_back(template_host);\r
+                       }\r
+                       catch(...){}\r
+               }\r
+\r
+               auto template_host_it = boost::find_if(template_hosts, [&](template_host template_host){return template_host.video_mode == desc.name;});\r
+               if(template_host_it == template_hosts.end())\r
+                       template_host_it = boost::find_if(template_hosts, [&](template_host template_host){return template_host.video_mode == L"";});\r
+\r
+               if(template_host_it != template_hosts.end())\r
+                       return *template_host_it;\r
+       }\r
+       catch(...){}\r
+               \r
+       template_host template_host;\r
+       template_host.filename = L"cg.fth";\r
+\r
+       for(auto it = boost::filesystem2::wdirectory_iterator(env::template_folder()); it != boost::filesystem2::wdirectory_iterator(); ++it)\r
+       {\r
+               if(boost::iequals(it->path().extension(), L"." + desc.name))\r
+               {\r
+                       template_host.filename = it->filename();\r
+                       break;\r
+               }\r
+       }\r
+\r
+       template_host.width =  desc.square_width;\r
+       template_host.height = desc.square_height;\r
+       return template_host;\r
+}\r
+\r
+class flash_renderer\r
+{      \r
+       struct com_init\r
+       {\r
+               HRESULT result_;\r
+\r
+               com_init()\r
+                       : result_(CoInitialize(nullptr))\r
+               {\r
+                       if(FAILED(result_))\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to initialize com-context for flash-player"));\r
+               }\r
+\r
+               ~com_init()\r
+               {\r
+                       if(SUCCEEDED(result_))\r
+                               ::CoUninitialize();\r
+               }\r
+       } com_init_;\r
+       \r
+       const safe_ptr<diagnostics::graph>                              graph_;\r
+       const size_t                                                                    width_;\r
+       const size_t                                                                    height_;\r
+       const std::wstring                                                              filename_;\r
+       const std::shared_ptr<core::frame_factory>              frame_factory_;\r
+       \r
+       CComObject<caspar::flash::FlashAxContainer>*    ax_;\r
+       safe_ptr<core::basic_frame>                                             head_;\r
+       bitmap                                                                                  bmp_;\r
+       \r
+       boost::timer                                                                    frame_timer_;\r
+       boost::timer                                                                    tick_timer_;\r
+\r
+       high_prec_timer                                                                 timer_;\r
+       \r
+public:\r
+       flash_renderer(const safe_ptr<diagnostics::graph>& graph, const std::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, int width, int height) \r
+               : graph_(graph)\r
+               , width_(width)\r
+               , height_(height)\r
+               , filename_(filename)\r
+               , frame_factory_(frame_factory)\r
+               , ax_(nullptr)\r
+               , head_(core::basic_frame::empty())\r
+               , bmp_(width, height)\r
+       {               \r
+               graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));\r
+               graph_->set_color("param", diagnostics::color(1.0f, 0.5f, 0.0f));       \r
+               graph_->set_color("sync", diagnostics::color(0.8f, 0.3f, 0.2f));                        \r
+               \r
+               if(FAILED(CComObject<caspar::flash::FlashAxContainer>::CreateInstance(&ax_)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to create FlashAxContainer"));\r
+               \r
+               ax_->set_print([this]{return print();});\r
+\r
+               if(FAILED(ax_->CreateAxControl()))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to Create FlashAxControl"));\r
+               \r
+               CComPtr<IShockwaveFlash> spFlash;\r
+               if(FAILED(ax_->QueryControl(&spFlash)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to Query FlashAxControl"));\r
+                                                                                               \r
+               if(FAILED(spFlash->put_Playing(true)) )\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to start playing Flash"));\r
+\r
+               if(FAILED(spFlash->put_Movie(CComBSTR(filename.c_str()))))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to Load Template Host"));\r
+                                                                               \r
+               if(FAILED(spFlash->put_ScaleMode(2)))  //Exact fit. Scale without respect to the aspect ratio.\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to Set Scale Mode"));\r
+                                               \r
+               ax_->SetSize(width_, height_);          \r
+               render_frame(false);\r
+       \r
+               CASPAR_LOG(info) << print() << L" Initialized.";\r
+       }\r
+\r
+       ~flash_renderer()\r
+       {               \r
+               if(ax_)\r
+               {\r
+                       ax_->DestroyAxControl();\r
+                       ax_->Release();\r
+               }\r
+               graph_->set_value("tick-time", 0.0f);\r
+               graph_->set_value("frame-time", 0.0f);\r
+               CASPAR_LOG(info) << print() << L" Uninitialized.";\r
+       }\r
+       \r
+       std::wstring call(const std::wstring& param)\r
+       {               \r
+               std::wstring result;\r
+\r
+               CASPAR_LOG(trace) << print() << " Call: " << param;\r
+\r
+               if(!ax_->FlashCall(param, result))\r
+                       CASPAR_LOG(warning) << print() << L" Flash call failed:" << param;//BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Flash function call failed.") << arg_name_info("param") << arg_value_info(narrow(param)));\r
+               graph_->set_tag("param");\r
+\r
+               return result;\r
+       }\r
+       \r
+       safe_ptr<core::basic_frame> render_frame(double sync)\r
+       {\r
+               float frame_time = 1.0f/ax_->GetFPS();\r
+\r
+               graph_->set_value("tick-time", static_cast<float>(tick_timer_.elapsed()/frame_time)*0.5f);\r
+               tick_timer_.restart();\r
+\r
+               if(ax_->IsEmpty())\r
+                       return core::basic_frame::empty();              \r
+               \r
+               if(sync > 0.00001)                      \r
+                       timer_.tick(frame_time*sync); // This will block the thread.\r
+               else\r
+                       graph_->set_tag("sync");\r
+\r
+               graph_->set_value("sync", sync);\r
+                       \r
+               frame_timer_.restart();\r
+\r
+               ax_->Tick();\r
+               if(ax_->InvalidRect())\r
+               {\r
+                       fast_memclr(bmp_.data(), width_*height_*4);\r
+                       ax_->DrawControl(bmp_);\r
+               \r
+                       core::pixel_format_desc desc;\r
+                       desc.pix_fmt = core::pixel_format::bgra;\r
+                       desc.planes.push_back(core::pixel_format_desc::plane(width_, height_, 4));\r
+                       auto frame = frame_factory_->create_frame(this, desc);\r
+\r
+                       if(frame->image_data().size() == static_cast<int>(width_*height_*4))\r
+                       {\r
+                               fast_memcpy(frame->image_data().begin(), bmp_.data(), width_*height_*4);\r
+                               frame->commit();\r
+                               head_ = frame;\r
+                       }\r
+               }               \r
+                                       \r
+               MSG msg;\r
+               while(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) // DO NOT REMOVE THE MESSAGE DISPATCH LOOP. Without this some stuff doesn't work!  \r
+               {\r
+                       if(msg.message == WM_TIMER && msg.wParam == 3 && msg.lParam == 0) // We tick this inside FlashAxContainer\r
+                               continue;\r
+                       \r
+                       TranslateMessage(&msg);\r
+                       DispatchMessage(&msg);                  \r
+               }\r
+                                                                               \r
+               graph_->set_value("frame-time", static_cast<float>(frame_timer_.elapsed()/frame_time)*0.5f);\r
+               return head_;\r
+       }\r
+\r
+       bool is_empty() const\r
+       {\r
+               return ax_->IsEmpty();\r
+       }\r
+\r
+       double fps() const\r
+       {\r
+               return ax_->GetFPS();   \r
+       }\r
+       \r
+       std::wstring print()\r
+       {\r
+               return L"flash-player[" + boost::filesystem::wpath(filename_).filename() \r
+                                 + L"|" + boost::lexical_cast<std::wstring>(width_)\r
+                                 + L"x" + boost::lexical_cast<std::wstring>(height_)\r
+                                 + L"]";               \r
+       }\r
+};\r
+\r
+struct flash_producer : public core::frame_producer\r
+{      \r
+       const std::wstring                                                                                      filename_;      \r
+       const safe_ptr<core::frame_factory>                                                     frame_factory_;\r
+       const int                                                                                                       width_;\r
+       const int                                                                                                       height_;\r
+       const int                                                                                                       buffer_size_;\r
+\r
+       tbb::atomic<int>                                                                                        fps_;\r
+\r
+       safe_ptr<diagnostics::graph>                                                            graph_;\r
+\r
+       std::queue<safe_ptr<core::basic_frame>>                                         frame_buffer_;\r
+       tbb::concurrent_bounded_queue<safe_ptr<core::basic_frame>>      output_buffer_;\r
+       \r
+       mutable tbb::spin_mutex                                                                         last_frame_mutex_;\r
+       safe_ptr<core::basic_frame>                                                                     last_frame_;\r
+               \r
+       std::unique_ptr<flash_renderer>                                                         renderer_;\r
+\r
+       executor                                                                                                        executor_;      \r
+public:\r
+       flash_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, size_t width, size_t height) \r
+               : filename_(filename)           \r
+               , frame_factory_(frame_factory)\r
+               , last_frame_(core::basic_frame::empty())\r
+               , width_(width > 0 ? width : frame_factory->get_video_format_desc().width)\r
+               , height_(height > 0 ? height : frame_factory->get_video_format_desc().height)\r
+               , buffer_size_(env::properties().get(L"configuration.flash.buffer-depth", frame_factory_->get_video_format_desc().fps > 30.0 ? 4 : 2))\r
+               , executor_(L"flash_producer")\r
+       {       \r
+               fps_ = 0;\r
+        \r
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.9f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+               \r
+               renderer_.reset(new flash_renderer(graph_, frame_factory_, filename_, width_, height_));\r
+\r
+               while(output_buffer_.size() < buffer_size_)\r
+                       output_buffer_.push(core::basic_frame::empty());\r
+       }\r
+\r
+       ~flash_producer()\r
+       {\r
+               executor_.invoke([this]\r
+               {\r
+                       renderer_.reset();\r
+               }, high_priority);\r
+       }\r
+\r
+       // frame_producer\r
+               \r
+       virtual safe_ptr<core::basic_frame> receive(int) override\r
+       {                                       \r
+               auto frame = core::basic_frame::late();\r
+               \r
+               if(output_buffer_.try_pop(frame))       \r
+                       next();\r
+               else\r
+                       graph_->set_tag("late-frame");\r
+\r
+               return frame;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return lock(last_frame_mutex_, [this]\r
+               {\r
+                       return last_frame_;\r
+               });\r
+       }               \r
+       \r
+       virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
+       {       \r
+               return executor_.begin_invoke([this, param]() -> std::wstring\r
+               {                       \r
+                       try\r
+                       {\r
+                               if(!renderer_)\r
+                               {\r
+                                       renderer_.reset(new flash_renderer(graph_, frame_factory_, filename_, width_, height_));\r
+\r
+                                       while(output_buffer_.size() < buffer_size_)\r
+                                               output_buffer_.push(core::basic_frame::empty());\r
+                               }\r
+\r
+                               return renderer_->call(param);  \r
+\r
+                               //const auto& format_desc = frame_factory_->get_video_format_desc();\r
+                               //if(abs(context_->fps() - format_desc.fps) > 0.01 && abs(context_->fps()/2.0 - format_desc.fps) > 0.01)\r
+                               //      CASPAR_LOG(warning) << print() << " Invalid frame-rate: " << context_->fps() << L". Should be either " << format_desc.fps << L" or " << format_desc.fps*2.0 << L".";\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               renderer_.reset(nullptr);\r
+                       }\r
+\r
+                       return L"";\r
+               });\r
+       }\r
+               \r
+       virtual std::wstring print() const override\r
+       { \r
+               return L"flash[" + boost::filesystem::wpath(filename_).filename() + L"|" + boost::lexical_cast<std::wstring>(fps_) + L"]";              \r
+       }       \r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"flash-producer");\r
+               return info;\r
+       }\r
+\r
+       // flash_producer\r
+       \r
+       void next()\r
+       {       \r
+               executor_.begin_invoke([this]\r
+               {\r
+                       if(!renderer_)\r
+                               frame_buffer_.push(core::basic_frame::empty());\r
+\r
+                       if(frame_buffer_.empty())\r
+                       {\r
+                               auto format_desc = frame_factory_->get_video_format_desc();\r
+                                       \r
+                               if(abs(renderer_->fps()/2.0 - format_desc.fps) < 2.0) // flash == 2 * format -> interlace\r
+                               {\r
+                                       auto frame1 = render_frame();\r
+                                       auto frame2 = render_frame();\r
+                                       frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.field_mode));\r
+                               }\r
+                               else if(abs(renderer_->fps() - format_desc.fps/2.0) < 2.0) // format == 2 * flash -> duplicate\r
+                               {\r
+                                       auto frame = render_frame();\r
+                                       frame_buffer_.push(frame);\r
+                                       frame_buffer_.push(frame);\r
+                               }\r
+                               else //if(abs(renderer_->fps() - format_desc_.fps) < 0.1) // format == flash -> simple\r
+                               {\r
+                                       auto frame = render_frame();\r
+                                       frame_buffer_.push(frame);\r
+                               }\r
+                                               \r
+                               fps_.fetch_and_store(static_cast<int>(renderer_->fps()*100.0));                         \r
+                               graph_->set_text(print());\r
+                       \r
+                               if(renderer_->is_empty())                       \r
+                                       renderer_.reset();\r
+                       }\r
+\r
+                       output_buffer_.push(std::move(frame_buffer_.front()));\r
+                       frame_buffer_.pop();\r
+               });\r
+       }\r
+\r
+       safe_ptr<core::basic_frame> render_frame()\r
+       {       \r
+               double ratio = std::min(1.0, static_cast<double>(output_buffer_.size())/static_cast<double>(std::max(1, buffer_size_ - 1)));\r
+               double sync  = 2*ratio - ratio*ratio;\r
+\r
+               auto frame = renderer_->render_frame(sync);\r
+               lock(last_frame_mutex_, [&]\r
+               {\r
+                       last_frame_ = frame;\r
+               });\r
+               return frame;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       auto template_host = get_template_host(frame_factory->get_video_format_desc());\r
+       \r
+       auto filename = env::template_folder() + L"\\" + template_host.filename;\r
+       \r
+       if(!boost::filesystem::exists(filename))\r
+               BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(narrow(filename)));  \r
+\r
+       return create_producer_destroy_proxy(\r
+                  create_producer_print_proxy(\r
+                       make_safe<flash_producer>(frame_factory, filename, template_host.width, template_host.height)));\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_swf_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params) \r
+{\r
+       auto filename = env::media_folder() + L"\\" + params.at(0) + L".swf";\r
+       \r
+       if(!boost::filesystem::exists(filename))\r
+               return core::frame_producer::empty();\r
+\r
+       swf_t::header_t header(filename);\r
+\r
+       return create_producer_destroy_proxy(\r
+                  create_producer_print_proxy(\r
+                       make_safe<flash_producer>(frame_factory, filename, header.frame_width, header.frame_height)));\r
+}\r
+\r
+std::wstring find_template(const std::wstring& template_name)\r
+{\r
+       if(boost::filesystem::exists(template_name + L".ft")) \r
+               return template_name + L".ft";\r
+       \r
+       if(boost::filesystem::exists(template_name + L".ct"))\r
+               return template_name + L".ct";\r
+       \r
+       if(boost::filesystem::exists(template_name + L".swf"))\r
+               return template_name + L".swf";\r
+\r
+       return L"";\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/producer/flash_producer.h b/modules/flash/producer/flash_producer.h
new file mode 100644 (file)
index 0000000..fec8d16
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <vector>\r
+#include <string>\r
+\r
+namespace caspar { namespace flash {\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_swf_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+std::wstring find_template(const std::wstring& templateName);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/util/swf.cpp b/modules/flash/util/swf.cpp
new file mode 100644 (file)
index 0000000..0c2cb95
--- /dev/null
@@ -0,0 +1,184 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "swf.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <zlib.h>\r
+\r
+#include <fstream>\r
+#include <streambuf>\r
+\r
+namespace caspar { namespace flash {\r
+       \r
+std::vector<char> decompress_one_file(const std::vector<char>& in_data, uLong buf_size = 5000000)\r
+{\r
+       if(buf_size > 300*1000000)\r
+               BOOST_THROW_EXCEPTION(file_read_error());\r
+\r
+       std::vector<char> out_data(buf_size, 0);\r
+\r
+       auto ret = uncompress((Bytef*)out_data.data(), &buf_size, (Bytef*)in_data.data(), in_data.size());\r
+\r
+       if(ret == Z_BUF_ERROR)\r
+               return decompress_one_file(in_data, buf_size*2);\r
+\r
+       if(ret != Z_OK)\r
+               BOOST_THROW_EXCEPTION(file_read_error());\r
+\r
+       out_data.resize(buf_size);\r
+\r
+       return out_data;\r
+}\r
+\r
+std::string read_template_meta_info(const std::wstring& filename)\r
+{\r
+       auto file = std::fstream(filename, std::ios::in | std::ios::binary);\r
+\r
+       if(!file)\r
+               BOOST_THROW_EXCEPTION(file_read_error());\r
+       \r
+       char head[4] = {};\r
+       file.read(head, 3);\r
+       \r
+       std::vector<char> data;\r
+       \r
+       file.seekg(0, std::ios::end);   \r
+       data.reserve(static_cast<size_t>(file.tellg()));\r
+       file.seekg(0, std::ios::beg);\r
+\r
+       if(strcmp(head, "CWS") == 0)\r
+       {\r
+               file.seekg(8, std::ios::beg);\r
+               std::copy((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>(), std::back_inserter(data));\r
+               data = decompress_one_file(data);\r
+       }\r
+       else\r
+       {\r
+               file.seekg(0, std::ios::end);   \r
+               data.reserve(static_cast<size_t>(file.tellg()));\r
+               file.seekg(0, std::ios::beg);\r
+\r
+               std::copy((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>(), std::back_inserter(data));\r
+       }\r
+       \r
+       std::string beg_str = "<template version";\r
+       std::string end_str = "</template>";\r
+       auto beg_it = std::find_end(data.begin(), data.end(), beg_str.begin(), beg_str.end());\r
+       auto end_it = std::find_end(beg_it, data.end(), end_str.begin(), end_str.end());\r
+       \r
+       if(beg_it == data.end() || end_it == data.end())\r
+               BOOST_THROW_EXCEPTION(file_read_error());\r
+                       \r
+       return std::string(beg_it, end_it+end_str.size());\r
+}\r
+\r
+int extractDimensions(const unsigned char* _data);\r
+\r
+swf_t::header_t::header_t(const std::wstring& filename)\r
+       : valid(false)\r
+{\r
+       auto stream = std::fstream();\r
+       stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\r
+       stream.open(filename, std::ios::in | std::ios::binary);\r
+       stream.read(reinterpret_cast<char*>(this), 8);\r
+               \r
+       const std::array<std::uint8_t, 3> s1 = {'F', 'W', 'S'};\r
+       const std::array<std::uint8_t, 3> s2 = {'C', 'W', 'S'};\r
+\r
+       if(this->signature != s1 && this->signature != s2)\r
+               return;\r
+       \r
+       _byteswap_ulong(this->file_length);\r
+                       \r
+       std::vector<char> file_data;\r
+       std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\r
+\r
+       std::array<char, 32> data;\r
+       uLongf file_size = 32;\r
+       auto ret = uncompress(reinterpret_cast<Bytef*>(data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));\r
+       \r
+       if(ret == Z_DATA_ERROR)\r
+               BOOST_THROW_EXCEPTION(io_error());\r
+\r
+       // http://thenobody.blog.matfyz.sk/p13084-how-to-get-dimensions-of-a-swf-file\r
+\r
+       unsigned char nbits = reinterpret_cast<unsigned char*>(data.data())[0];\r
+\r
+       unsigned int size = nbits >> 3;                                                                         // remove overlaping 3 bits\r
+\r
+       unsigned long dims[4] = {};\r
+       unsigned long neg_root = 1 << (size-1);                                                         // numbers are signed, i.e. leftmost bit denotes -\r
+\r
+       unsigned int bi_offset = (size % 8) ? (8-(size % 8)) : 0;                       // offset of bit numbers depending on specified size\r
+       unsigned int by_offset = (size + bi_offset) / 8;                                        // offest of bytes\r
+       unsigned int ioffset;                                                                                           // floating byte offset during iteration\r
+       unsigned long ibuf = (unsigned long) (nbits % 8);                                       // actual result - starts with last 3 bits of first byte\r
+\r
+       for(auto i = 0; i < 4; ++i)\r
+       {\r
+               ioffset = by_offset * i;\r
+\r
+               for(unsigned int j = 0; j < by_offset; ++j)\r
+               {\r
+                       ibuf <<= 8;\r
+                       ibuf +=  reinterpret_cast<unsigned char*>(data.data())[1+ioffset+j];\r
+               }\r
+\r
+               dims[i] = (ibuf >> (3 + bi_offset + (i * bi_offset))) / 20;             // coordinates in twips, so divide by 20 for pixels\r
+\r
+               if(dims[i] >= neg_root)                                                                                 // if the leftmost bit is 1 number is negative          \r
+                       dims[i] = (-1) * ( neg_root - (dims[i] - neg_root) );           // convert to negative number           \r
+\r
+               int expn = 3 + bi_offset + (i * bi_offset);                                             // bit divider for ...\r
+               ibuf = ibuf % (1 << (expn-1));                                                                  // ... buffered number \r
+       }\r
+       \r
+       this->frame_width  = dims[1] - dims[0];                                                         // max - mix\r
+       this->frame_height = dims[3] - dims[2]; \r
+\r
+       this->valid = true;\r
+}\r
+\r
+swf_t::swf_t(const std::wstring& filename)\r
+       : header(filename)\r
+{\r
+       auto stream = std::fstream();\r
+       stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\r
+       stream.open(filename, std::ios::in | std::ios::binary);         \r
+       stream.seekg(8, std::fstream::beg);\r
+\r
+       this->data.resize(this->header.file_length - 8);\r
+       \r
+       std::vector<char> file_data;\r
+       std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\r
+\r
+       uLongf file_size = this->header.file_length;\r
+       auto ret = uncompress(reinterpret_cast<Bytef*>(this->data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));\r
+\r
+       if(ret != Z_OK)\r
+               BOOST_THROW_EXCEPTION(io_error());\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/flash/util/swf.h b/modules/flash/util/swf.h
new file mode 100644 (file)
index 0000000..2017c6d
--- /dev/null
@@ -0,0 +1,54 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <cstdint>\r
+#include <string>\r
+\r
+namespace caspar { namespace flash {\r
+\r
+std::string read_template_meta_info(const std::wstring& filename);\r
+\r
+struct swf_t\r
+{\r
+       struct header_t\r
+       {\r
+               header_t(const std::wstring& filename);\r
+\r
+               std::array<std::uint8_t, 3> signature;\r
+               std::uint8_t                            version;\r
+               std::uint32_t                           file_length;\r
+               std::uint32_t                           frame_width;\r
+               std::uint32_t                           frame_height;\r
+               std::uint16_t                           frame_rate;\r
+               std::uint16_t                           frame_count;\r
+\r
+               bool                                            valid;\r
+\r
+       } header;\r
+       \r
+       std::vector<char>                               data;\r
+       \r
+       swf_t(const std::wstring& filename);\r
+};\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/consumer/image_consumer.cpp b/modules/image/consumer/image_consumer.cpp
new file mode 100644 (file)
index 0000000..ce3d368
--- /dev/null
@@ -0,0 +1,149 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "image_consumer.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/env.h>\r
+#include <common/log/log.h>\r
+#include <common/utility/string.h>\r
+#include <common/concurrency/future_util.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+#include <boost/thread.hpp>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <FreeImage.h>\r
+#include <vector>\r
+#include <algorithm>\r
+\r
+#include "../util/image_view.h"\r
+\r
+namespace caspar { namespace image {\r
+\r
+void write_cropped_png(\r
+               const safe_ptr<core::read_frame>& frame,\r
+               const core::video_format_desc& format_desc,\r
+               const boost::filesystem::wpath& output_file,\r
+               int width,\r
+               int height)\r
+{\r
+       auto bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Allocate(width, height, 32), FreeImage_Unload);\r
+       image_view<bgra_pixel> destination_view(FreeImage_GetBits(bitmap.get()), width, height);\r
+       image_view<bgra_pixel> complete_frame(const_cast<uint8_t*>(frame->image_data().begin()), format_desc.width, format_desc.height);\r
+       auto thumbnail_view = complete_frame.subview(0, 0, width, height);\r
+\r
+       std::copy(thumbnail_view.begin(), thumbnail_view.end(), destination_view.begin());\r
+       FreeImage_FlipVertical(bitmap.get());\r
+       FreeImage_SaveU(FIF_PNG, bitmap.get(), output_file.string().c_str(), 0);\r
+}\r
+\r
+struct image_consumer : public core::frame_consumer\r
+{\r
+       core::video_format_desc format_desc_;\r
+       std::wstring                    filename_;\r
+public:\r
+\r
+       // frame_consumer\r
+\r
+       image_consumer(const std::wstring& filename)\r
+               : filename_(filename)\r
+       {\r
+       }\r
+\r
+       virtual void initialize(const core::video_format_desc& format_desc, int) override\r
+       {\r
+               format_desc_ = format_desc;\r
+       }\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override\r
+       {                               \r
+               auto format_desc = format_desc_;\r
+               auto filename = filename_;\r
+\r
+               boost::thread async([format_desc, frame, filename]\r
+               {\r
+                       try\r
+                       {\r
+                               auto filename2 = filename;\r
+\r
+                               if (filename2.empty())\r
+                                       filename2 = env::media_folder() + widen(boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time())) + L".png";\r
+                               else\r
+                                       filename2 = env::media_folder() + filename2 + L".png";\r
+\r
+                               auto bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Allocate(format_desc.width, format_desc.height, 32), FreeImage_Unload);\r
+                               memcpy(FreeImage_GetBits(bitmap.get()), frame->image_data().begin(), frame->image_size());\r
+                               FreeImage_FlipVertical(bitmap.get());\r
+                               FreeImage_SaveU(FIF_PNG, bitmap.get(), filename2.c_str(), 0);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+               });\r
+               async.detach();\r
+\r
+               return wrap_as_future(false);\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"image[]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"image-consumer");\r
+               return info;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 100;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 1 || params[0] != L"IMAGE")\r
+               return core::frame_consumer::empty();\r
+\r
+       std::wstring filename;\r
+\r
+       if (params.size() > 1)\r
+               filename = params[1];\r
+\r
+       return make_safe<image_consumer>(filename);\r
+}\r
+\r
+}}\r
diff --git a/modules/image/consumer/image_consumer.h b/modules/image/consumer/image_consumer.h
new file mode 100644 (file)
index 0000000..d5e482b
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/filesystem.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+       class read_frame;\r
+       struct video_format_desc;\r
+}\r
+\r
+namespace image {\r
+\r
+void write_cropped_png(\r
+               const safe_ptr<core::read_frame>& frame,\r
+               const core::video_format_desc& format_desc,\r
+               const boost::filesystem::wpath& output_file,\r
+               int width,\r
+               int height);\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/image.cpp b/modules/image/image.cpp
new file mode 100644 (file)
index 0000000..82517a4
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "image.h"\r
+\r
+#include "producer/image_producer.h"\r
+#include "producer/image_scroll_producer.h"\r
+#include "consumer/image_consumer.h"\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+#include <common/utility/string.h>\r
+\r
+#include <FreeImage.h>\r
+\r
+namespace caspar { namespace image {\r
+\r
+void init()\r
+{\r
+       core::register_producer_factory(create_scroll_producer);\r
+       core::register_producer_factory(create_producer);\r
+       core::register_thumbnail_producer_factory(create_thumbnail_producer);\r
+       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+}\r
+\r
+std::wstring get_version()\r
+{\r
+       return widen(std::string(FreeImage_GetVersion()));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/image.h b/modules/image/image.h
new file mode 100644 (file)
index 0000000..512afff
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+\r
+namespace caspar { namespace image {\r
+\r
+void init();\r
+\r
+std::wstring get_version();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/image.vcxproj b/modules/image/image.vcxproj
new file mode 100644 (file)
index 0000000..e539957
--- /dev/null
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}</ProjectGuid>\r
+    <RootNamespace>image</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>image</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\FreeImage\Dist\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\FreeImage\Dist\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\FreeImage\Dist\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\FreeImage\Dist\;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\image_consumer.cpp" />\r
+    <ClCompile Include="image.cpp" />\r
+    <ClCompile Include="producer\image_producer.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\image_scroll_producer.cpp" />\r
+    <ClCompile Include="util\image_loader.cpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\image_consumer.h" />\r
+    <ClInclude Include="image.h" />\r
+    <ClInclude Include="producer\image_producer.h" />\r
+    <ClInclude Include="producer\image_scroll_producer.h" />\r
+    <ClInclude Include="util\image_algorithms.h" />\r
+    <ClInclude Include="util\image_loader.h" />\r
+    <ClInclude Include="util\image_view.h" />\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/image/image.vcxproj.filters b/modules/image/image.vcxproj.filters
new file mode 100644 (file)
index 0000000..05665fc
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{9b9cf86c-b679-4e0f-88bc-e0bf48db9173}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{46bdb484-2321-419b-a1c4-4b8d5d49fba9}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\util">\r
+      <UniqueIdentifier>{6abd09ae-2ad7-41fa-bfa5-f4614a07be8c}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{15311b81-1e0d-4114-9bf8-b8f74b292a0f}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="producer\image_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\image_loader.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="image.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\image_scroll_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="consumer\image_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="producer\image_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\image_loader.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="image.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\image_scroll_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="consumer\image_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\image_algorithms.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\image_view.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/image/producer/image_producer.cpp b/modules/image/producer/image_producer.cpp
new file mode 100644 (file)
index 0000000..0f562bc
--- /dev/null
@@ -0,0 +1,129 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "image_producer.h"\r
+\r
+#include "../util/image_loader.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/env.h>\r
+#include <common/log/log.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <algorithm>\r
+\r
+using namespace boost::assign;\r
+\r
+namespace caspar { namespace image {\r
+\r
+struct image_producer : public core::frame_producer\r
+{      \r
+       const std::wstring filename_;\r
+       safe_ptr<core::basic_frame> frame_;\r
+       \r
+       explicit image_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename) \r
+               : filename_(filename)\r
+               , frame_(core::basic_frame::empty())    \r
+       {\r
+               auto bitmap = load_image(filename_);\r
+               FreeImage_FlipVertical(bitmap.get());\r
+               \r
+               core::pixel_format_desc desc;\r
+               desc.pix_fmt = core::pixel_format::bgra;\r
+               desc.planes.push_back(core::pixel_format_desc::plane(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), 4));\r
+               auto frame = frame_factory->create_frame(this, desc);\r
+\r
+               std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
+               frame->commit();\r
+               frame_ = std::move(frame);\r
+       }\r
+       \r
+       // frame_producer\r
+\r
+       virtual safe_ptr<core::basic_frame> receive(int) override\r
+       {\r
+               return frame_;\r
+       }\r
+               \r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return frame_;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
+       {\r
+               return frame_;\r
+       }\r
+               \r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"image_producer[" + filename_ + L"]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"image-producer");\r
+               info.add(L"filename", filename_);\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_raw_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       static const std::vector<std::wstring> extensions = list_of(L"png")(L"tga")(L"bmp")(L"jpg")(L"jpeg")(L"gif")(L"tiff")(L"tif")(L"jp2")(L"jpx")(L"j2k")(L"j2c");\r
+       std::wstring filename = env::media_folder() + L"\\" + params[0];\r
+       \r
+       auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
+               {                                       \r
+                       return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
+               });\r
+\r
+       if(ext == extensions.end())\r
+               return core::frame_producer::empty();\r
+\r
+       return make_safe<image_producer>(frame_factory, filename + L"." + *ext);\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       auto raw_producer = create_raw_producer(frame_factory, params);\r
+\r
+       if (raw_producer == core::frame_producer::empty())\r
+               return raw_producer;\r
+\r
+       return create_producer_print_proxy(raw_producer);\r
+}\r
+\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       return create_raw_producer(frame_factory, params);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/producer/image_producer.h b/modules/image/producer/image_producer.h
new file mode 100644 (file)
index 0000000..3d95d08
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace image {\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/producer/image_scroll_producer.cpp b/modules/image/producer/image_scroll_producer.cpp
new file mode 100644 (file)
index 0000000..558900e
--- /dev/null
@@ -0,0 +1,441 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "image_scroll_producer.h"\r
+\r
+#include "../util/image_loader.h"\r
+#include "../util/image_view.h"\r
+#include "../util/image_algorithms.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/mixer/write_frame.h>\r
+\r
+#include <common/env.h>\r
+#include <common/log/log.h>\r
+#include <common/memory/memclr.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/tweener.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/gil/gil_all.hpp>\r
+\r
+#include <algorithm>\r
+#include <array>\r
+#include <boost/math/special_functions/round.hpp>\r
+#include <boost/scoped_array.hpp>\r
+\r
+using namespace boost::assign;\r
+\r
+namespace caspar { namespace image {\r
+\r
+struct image_scroll_producer : public core::frame_producer\r
+{      \r
+       const std::wstring                                                      filename_;\r
+       std::vector<safe_ptr<core::basic_frame>>        frames_;\r
+       core::video_format_desc                                         format_desc_;\r
+       size_t                                                                          width_;\r
+       size_t                                                                          height_;\r
+\r
+       double                                                                          delta_;\r
+       double                                                                          speed_;\r
+\r
+       int                                                                                     start_offset_x_;\r
+       int                                                                                     start_offset_y_;\r
+       bool                                                                            progressive_;\r
+\r
+       safe_ptr<core::basic_frame>                                     last_frame_;\r
+       \r
+       explicit image_scroll_producer(\r
+               const safe_ptr<core::frame_factory>& frame_factory, \r
+               const std::wstring& filename, \r
+               double speed,\r
+               double duration,\r
+               int motion_blur_px = 0,\r
+               bool premultiply_with_alpha = false,\r
+               bool progressive = false) \r
+               : filename_(filename)\r
+               , delta_(0)\r
+               , format_desc_(frame_factory->get_video_format_desc())\r
+               , speed_(speed)\r
+               , progressive_(progressive)\r
+               , last_frame_(core::basic_frame::empty())\r
+       {\r
+               start_offset_x_ = 0;\r
+               start_offset_y_ = 0;\r
+\r
+               auto bitmap = load_image(filename_);\r
+               FreeImage_FlipVertical(bitmap.get());\r
+\r
+               width_  = FreeImage_GetWidth(bitmap.get());\r
+               height_ = FreeImage_GetHeight(bitmap.get());\r
+\r
+               bool vertical = width_ == format_desc_.width;\r
+               bool horizontal = height_ == format_desc_.height;\r
+\r
+               if (!vertical && !horizontal)\r
+                       BOOST_THROW_EXCEPTION(\r
+                               caspar::invalid_argument() << msg_info("Neither width nor height matched the video resolution"));\r
+\r
+               if (vertical)\r
+               {\r
+                       if (duration != 0.0)\r
+                       {\r
+                               double total_num_pixels = format_desc_.height * 2 + height_;\r
+\r
+                               speed_ = total_num_pixels / (duration * format_desc_.fps * static_cast<double>(format_desc_.field_count));\r
+\r
+                               if (std::abs(speed_) > 1.0)\r
+                                       speed_ = std::ceil(speed_);\r
+                       }\r
+\r
+                       if (speed_ < 0.0)\r
+                               start_offset_y_ = height_ + format_desc_.height;\r
+               }\r
+               else\r
+               {\r
+                       if (duration != 0.0)\r
+                       {\r
+                               double total_num_pixels = format_desc_.width * 2 + width_;\r
+\r
+                               speed_ = total_num_pixels / (duration * format_desc_.fps * static_cast<double>(format_desc_.field_count));\r
+\r
+                               if (std::abs(speed_) > 1.0)\r
+                                       speed_ = std::ceil(speed_);\r
+                       }\r
+\r
+                       if (speed_ > 0.0)\r
+                               start_offset_x_ = format_desc_.width - (width_ % format_desc_.width);\r
+                       else\r
+                               start_offset_x_ = format_desc_.width - (width_ % format_desc_.width) + width_ + format_desc_.width;\r
+               }\r
+\r
+               auto bytes = FreeImage_GetBits(bitmap.get());\r
+               int count = width_*height_*4;\r
+               image_view<bgra_pixel> original_view(bytes, width_, height_);\r
+\r
+               if (premultiply_with_alpha)\r
+                       premultiply(original_view);\r
+\r
+               boost::scoped_array<uint8_t> blurred_copy;\r
+\r
+               if (motion_blur_px > 0)\r
+               {\r
+                       double angle = 3.14159265 / 2; // Up\r
+\r
+                       if (horizontal && speed_ < 0)\r
+                               angle *= 2; // Left\r
+                       else if (vertical && speed > 0)\r
+                               angle *= 3; // Down\r
+                       else if (horizontal && speed  > 0)\r
+                               angle = 0.0; // Right\r
+\r
+                       blurred_copy.reset(new uint8_t[count]);\r
+                       image_view<bgra_pixel> blurred_view(blurred_copy.get(), width_, height_);\r
+                       tweener_t blur_tweener = get_tweener(L"easeInQuad");\r
+                       blur(original_view, blurred_view, angle, motion_blur_px, blur_tweener);\r
+                       bytes = blurred_copy.get();\r
+                       bitmap.reset();\r
+               }\r
+\r
+               if (vertical)\r
+               {\r
+                       int n = 1;\r
+\r
+                       while(count > 0)\r
+                       {\r
+                               core::pixel_format_desc desc;\r
+                               desc.pix_fmt = core::pixel_format::bgra;\r
+                               desc.planes.push_back(core::pixel_format_desc::plane(width_, format_desc_.height, 4));\r
+                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);\r
+\r
+                               if(count >= frame->image_data().size())\r
+                               {       \r
+                                       std::copy_n(bytes + count - frame->image_data().size(), frame->image_data().size(), frame->image_data().begin());\r
+                                       count -= frame->image_data().size();\r
+                               }\r
+                               else\r
+                               {\r
+                                       fast_memclr(frame->image_data().begin(), frame->image_data().size());   \r
+                                       std::copy_n(bytes, count, frame->image_data().begin() + format_desc_.size - count);\r
+                                       count = 0;\r
+                               }\r
+\r
+                               frame->commit();\r
+                               frames_.push_back(frame);\r
+\r
+                               // Set the relative position to the other image fragments\r
+                               frame->get_frame_transform().fill_translation[1] = - n++;\r
+                       }\r
+\r
+               }\r
+               else if (horizontal)\r
+               {\r
+                       int i = 0;\r
+                       while(count > 0)\r
+                       {\r
+                               core::pixel_format_desc desc;\r
+                               desc.pix_fmt = core::pixel_format::bgra;\r
+                               desc.planes.push_back(core::pixel_format_desc::plane(format_desc_.width, height_, 4));\r
+                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);\r
+                               if(count >= frame->image_data().size())\r
+                               {       \r
+                                       for(size_t y = 0; y < height_; ++y)\r
+                                               std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, format_desc_.width*4, frame->image_data().begin() + y * format_desc_.width*4);\r
+                                       \r
+                                       ++i;\r
+                                       count -= frame->image_data().size();\r
+                               }\r
+                               else\r
+                               {\r
+                                       fast_memclr(frame->image_data().begin(), frame->image_data().size());   \r
+                                       int width2 = width_ % format_desc_.width;\r
+                                       for(size_t y = 0; y < height_; ++y)\r
+                                               std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, width2*4, frame->image_data().begin() + y * format_desc_.width*4);\r
+\r
+                                       count = 0;\r
+                               }\r
+                       \r
+                               frame->commit();\r
+                               frames_.push_back(frame);\r
+                       }\r
+\r
+                       std::reverse(frames_.begin(), frames_.end());\r
+\r
+                       // Set the relative positions of the image fragments.\r
+                       for (size_t n = 0; n < frames_.size(); ++n)\r
+                       {\r
+                               double translation = - (static_cast<double>(n) + 1.0);\r
+                               frames_[n]->get_frame_transform().fill_translation[0] = translation;\r
+                       }\r
+               }\r
+\r
+               CASPAR_LOG(info) << print() << L" Initialized";\r
+       }\r
+\r
+       std::vector<safe_ptr<core::basic_frame>> get_visible()\r
+       {\r
+               std::vector<safe_ptr<core::basic_frame>> result;\r
+               result.reserve(frames_.size());\r
+\r
+               BOOST_FOREACH(auto& frame, frames_)\r
+               {\r
+                       auto& fill_translation = frame->get_frame_transform().fill_translation;\r
+\r
+                       if (width_ == format_desc_.width)\r
+                       {\r
+                               auto motion_offset_in_screens = (static_cast<double>(start_offset_y_) + delta_) / static_cast<double>(format_desc_.height);\r
+                               auto vertical_offset = fill_translation[1] + motion_offset_in_screens;\r
+\r
+                               if (vertical_offset < -1.0 || vertical_offset > 1.0)\r
+                               {\r
+                                       continue;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               auto motion_offset_in_screens = (static_cast<double>(start_offset_x_) + delta_) / static_cast<double>(format_desc_.width);\r
+                               auto horizontal_offset = fill_translation[0] + motion_offset_in_screens;\r
+\r
+                               if (horizontal_offset < -1.0 || horizontal_offset > 1.0)\r
+                               {\r
+                                       continue;\r
+                               }\r
+                       }\r
+\r
+                       result.push_back(frame);\r
+               }\r
+\r
+               return std::move(result);\r
+       }\r
+       \r
+       // frame_producer\r
+\r
+       safe_ptr<core::basic_frame> render_frame(bool allow_eof)\r
+       {\r
+               if(frames_.empty())\r
+                       return core::basic_frame::eof();\r
+               \r
+               auto result = make_safe<core::basic_frame>(get_visible());\r
+               auto& fill_translation = result->get_frame_transform().fill_translation;\r
+\r
+               if (width_ == format_desc_.width)\r
+               {\r
+                       if (static_cast<size_t>(std::abs(delta_)) >= height_ + format_desc_.height && allow_eof)\r
+                               return core::basic_frame::eof();\r
+\r
+                       fill_translation[1] = \r
+                               static_cast<double>(start_offset_y_) / static_cast<double>(format_desc_.height)\r
+                               + delta_ / static_cast<double>(format_desc_.height);\r
+               }\r
+               else\r
+               {\r
+                       if (static_cast<size_t>(std::abs(delta_)) >= width_ + format_desc_.width && allow_eof)\r
+                               return core::basic_frame::eof();\r
+\r
+                       fill_translation[0] = \r
+                               static_cast<double>(start_offset_x_) / static_cast<double>(format_desc_.width)\r
+                               + (delta_) / static_cast<double>(format_desc_.width);\r
+               }\r
+\r
+               return result;\r
+       }\r
+\r
+       safe_ptr<core::basic_frame> render_frame(bool allow_eof, bool advance_delta)\r
+       {\r
+               auto result = render_frame(allow_eof);\r
+\r
+               if (advance_delta)\r
+               {\r
+                       advance();\r
+               }\r
+\r
+               return result;\r
+       }\r
+\r
+       void advance()\r
+       {\r
+               delta_ += speed_;\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> receive(int) override\r
+       {\r
+               if (format_desc_.field_mode == core::field_mode::progressive || progressive_)\r
+               {\r
+                       return last_frame_ = render_frame(true, true);\r
+               }\r
+               else\r
+               {\r
+                       auto field1 = render_frame(true, true);\r
+                       auto field2 = render_frame(true, false);\r
+\r
+                       if (field1 != core::basic_frame::eof() && field2 == core::basic_frame::eof())\r
+                       {\r
+                               field2 = render_frame(false, true);\r
+                       }\r
+                       else\r
+                       {\r
+                               advance();\r
+                       }\r
+\r
+                       last_frame_ = field2;\r
+\r
+                       return core::basic_frame::interlace(field1, field2, format_desc_.field_mode);\r
+               }\r
+       }\r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return last_frame_;\r
+       }\r
+               \r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"image_scroll_producer[" + filename_ + L"]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"image-scroll-producer");\r
+               info.add(L"filename", filename_);\r
+               return info;\r
+       }\r
+\r
+       virtual uint32_t nb_frames() const override\r
+       {\r
+               if(width_ == format_desc_.width)\r
+               {\r
+                       auto length = (height_ + format_desc_.height * 2);\r
+                       return static_cast<uint32_t>(length / std::abs(speed_));// + length % std::abs(delta_));\r
+               }\r
+               else\r
+               {\r
+                       auto length = (width_ + format_desc_.width * 2);\r
+                       return static_cast<uint32_t>(length / std::abs(speed_));// + length % std::abs(delta_));\r
+               }\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_scroll_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       static const std::vector<std::wstring> extensions = list_of(L"png")(L"tga")(L"bmp")(L"jpg")(L"jpeg")(L"gif")(L"tiff")(L"tif")(L"jp2")(L"jpx")(L"j2k")(L"j2c");\r
+       std::wstring filename = env::media_folder() + L"\\" + params[0];\r
+       \r
+       auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
+               {                                       \r
+                       return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
+               });\r
+\r
+       if(ext == extensions.end())\r
+               return core::frame_producer::empty();\r
+       \r
+       double speed = 0.0;\r
+       double duration = 0.0;\r
+       auto speed_it = std::find(params.begin(), params.end(), L"SPEED");\r
+       if(speed_it != params.end())\r
+       {\r
+               if(++speed_it != params.end())\r
+                       speed = boost::lexical_cast<double>(*speed_it);\r
+       }\r
+\r
+       if (speed == 0)\r
+       {\r
+               auto duration_it = std::find(params.begin(), params.end(), L"DURATION");\r
+\r
+               if (duration_it != params.end() && ++duration_it != params.end())\r
+               {\r
+                       duration = boost::lexical_cast<double>(*duration_it);\r
+               }\r
+       }\r
+\r
+       if(speed == 0 && duration == 0)\r
+               return core::frame_producer::empty();\r
+\r
+       int motion_blur_px = 0;\r
+       auto blur_it = std::find(params.begin(), params.end(), L"BLUR");\r
+       if (blur_it != params.end() && ++blur_it != params.end())\r
+       {\r
+               motion_blur_px = boost::lexical_cast<int>(*blur_it);\r
+       }\r
+\r
+       bool premultiply_with_alpha = std::find(params.begin(), params.end(), L"PREMULTIPLY") != params.end();\r
+       bool progressive = std::find(params.begin(), params.end(), L"PROGRESSIVE") != params.end();\r
+\r
+       return create_producer_print_proxy(make_safe<image_scroll_producer>(\r
+               frame_factory, \r
+               filename + L"." + *ext, \r
+               -speed, \r
+               -duration, \r
+               motion_blur_px, \r
+               premultiply_with_alpha,\r
+               progressive));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/producer/image_scroll_producer.h b/modules/image/producer/image_scroll_producer.h
new file mode 100644 (file)
index 0000000..42d2a7d
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace image {\r
+\r
+safe_ptr<core::frame_producer> create_scroll_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/util/image_algorithms.h b/modules/image/util/image_algorithms.h
new file mode 100644 (file)
index 0000000..22845d4
--- /dev/null
@@ -0,0 +1,233 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/utility/tweener.h>\r
+\r
+#include <cmath>\r
+#include <boost/foreach.hpp>\r
+\r
+namespace caspar { namespace image {\r
+\r
+/**\r
+ * Helper for calculating the color of a pixel given any number of of other\r
+ * pixels (each with their own weight).\r
+ */\r
+class rgba_weighting\r
+{\r
+       int r, g, b, a;\r
+       int total_weight;\r
+public:\r
+       rgba_weighting()\r
+               : r(0), g(0), b(0), a(0), total_weight(0)\r
+       {\r
+       }\r
+\r
+       template<class RGBAPixel>\r
+       inline void add_pixel(const RGBAPixel& pixel, uint8_t weight)\r
+       {\r
+               r += pixel.r() * weight;\r
+               g += pixel.g() * weight;\r
+               b += pixel.b() * weight;\r
+               a += pixel.a() * weight;\r
+\r
+               total_weight += weight;\r
+       }\r
+\r
+       template<class RGBAPixel>\r
+       inline void store_result(RGBAPixel& pixel)\r
+       {\r
+               pixel.r() = static_cast<uint8_t>(r / total_weight);\r
+               pixel.g() = static_cast<uint8_t>(g / total_weight);\r
+               pixel.b() = static_cast<uint8_t>(b / total_weight);\r
+               pixel.a() = static_cast<uint8_t>(a / total_weight);\r
+       }\r
+};\r
+\r
+template<class T>\r
+std::vector<T> get_tweened_values(caspar::tweener_t& tweener, size_t num_values, T from, T to)\r
+{\r
+       std::vector<T> result;\r
+       result.reserve(num_values);\r
+\r
+       double start = static_cast<double>(from);\r
+       double delta = static_cast<double>(to - from);\r
+       double duration = static_cast<double>(num_values);\r
+\r
+       for (double t = 0; t < duration; ++t)\r
+       {\r
+               result.push_back(static_cast<T>(tweener(t, start, delta, duration - 1.0)));\r
+       }\r
+\r
+       return std::move(result);\r
+}\r
+\r
+/**\r
+ * Blur a source image and store the blurred result in a destination image.\r
+ * <p>\r
+ * The blur is done by weighting each relative pixel from a destination pixel\r
+ * position using a vector of relative x-y pairs. The further away a related\r
+ * pixel is the less weight it gets. A tweener is used to calculate the actual\r
+ * weights of each related pixel.\r
+ *\r
+ * @param src                      The source view. Has to model the ImageView\r
+ *                                 concept and have a pixel type modelling the\r
+ *                                 RGBAPixel concept.\r
+ * @param dst                      The destination view. Has to model the\r
+ *                                 ImageView concept and have a pixel type\r
+ *                                 modelling the RGBAPixel concept.\r
+ * @param motion_trail_coordinates The relative x-y positions to weight in for\r
+ *                                 each pixel.\r
+ * @param tweener                  The tweener to use for calculating the\r
+ *                                 weights of each relative position in the\r
+ *                                 motion trail.\r
+ */\r
+template<class SrcView, class DstView>\r
+void blur(\r
+       const SrcView& src,\r
+       DstView& dst,\r
+       const std::vector<std::pair<int, int>> motion_trail_coordinates, \r
+       caspar::tweener_t& tweener)\r
+{\r
+       int blur_px = motion_trail_coordinates.size();\r
+       auto tweened_weights_y = get_tweened_values<uint8_t>(tweener, blur_px + 2, 255, 0);\r
+       tweened_weights_y.pop_back();\r
+       tweened_weights_y.erase(tweened_weights_y.begin());\r
+\r
+       auto src_end = src.end();\r
+       auto dst_iter = dst.begin();\r
+\r
+       for (auto src_iter = src.begin(); src_iter != src_end; ++src_iter, ++dst_iter)\r
+       {\r
+               rgba_weighting w;\r
+\r
+               for (int i = 0; i < blur_px; ++i)\r
+               {\r
+                       auto& coordinate = motion_trail_coordinates[i];\r
+                       auto other_pixel = src.relative(src_iter, coordinate.first, coordinate.second);\r
+\r
+                       if (other_pixel == nullptr)\r
+                               break;\r
+\r
+                       w.add_pixel(*other_pixel, tweened_weights_y[i]);\r
+\r
+                       /*other_pixel = src.relative(src_iter, -coordinate.first, -coordinate.second);\r
+\r
+                       if (other_pixel)\r
+                               w.add_pixel(*other_pixel, tweened_weights_y[i]);*/\r
+               }\r
+\r
+               w.add_pixel(*src_iter, 255);\r
+               w.store_result(*dst_iter);\r
+       }\r
+}\r
+\r
+/**\r
+ * Calculate relative x-y coordinates of a straight line with a given angle and\r
+ * a given number of points.\r
+ *\r
+ * @param num_pixels    The number of pixels/points to create.\r
+ * @param angle_radians The angle of the line in radians.\r
+ *\r
+ * @return the x-y pairs.\r
+ */\r
+std::vector<std::pair<int, int>> get_line_points(int num_pixels, double angle_radians)\r
+{\r
+       std::vector<std::pair<int, int>> line_points;\r
+       line_points.reserve(num_pixels);\r
+\r
+       double delta_x = std::cos(angle_radians);\r
+       double delta_y = -std::sin(angle_radians); // In memory is revered\r
+       double max_delta = std::max(std::abs(delta_x), std::abs(delta_y));\r
+       double amplification = 1.0 / max_delta;\r
+       delta_x *= amplification;\r
+       delta_y *= amplification;\r
+\r
+       for (int i = 1; i <= num_pixels; ++i)\r
+               line_points.push_back(std::make_pair(\r
+                       static_cast<int>(std::floor(delta_x * static_cast<double>(i) + 0.5)), \r
+                       static_cast<int>(std::floor(delta_y * static_cast<double>(i) + 0.5))));\r
+\r
+       return std::move(line_points);\r
+}\r
+\r
+/**\r
+ * Directionally blur a source image modelling the ImageView concept and store\r
+ * the blurred image to a destination image also modelling the ImageView\r
+ * concept.\r
+ * <p>\r
+ * The pixel type of the views must model the RGBAPixel concept.\r
+ *\r
+ * @param src           The source image view. Has to model the ImageView\r
+ *                      concept and have a pixel type that models RGBAPixel.\r
+ * @param dst           The destiation image view. Has to model the ImageView\r
+ *                      concept and have a pixel type that models RGBAPixel.\r
+ * @param angle_radians The angle in radians to directionally blur the image.\r
+ * @param blur_px       The number of pixels of the blur.\r
+ * @param tweener       The tweener to use to create a pixel weighting curve\r
+ *                      with.\r
+ */\r
+template<class SrcView, class DstView>\r
+void blur(\r
+       const SrcView& src,\r
+       DstView& dst,\r
+       double angle_radians,\r
+       int blur_px, \r
+       caspar::tweener_t& tweener)\r
+{\r
+       auto motion_trail = get_line_points(blur_px, angle_radians);\r
+\r
+       blur(src, dst, motion_trail, tweener);\r
+}\r
+\r
+/**\r
+ * Premultiply with alpha for each pixel in an ImageView. The modifications is\r
+ * done in place. The pixel type of the ImageView must model the RGBAPixel\r
+ * concept.\r
+ *\r
+ * @param view_to_modify The image view to premultiply in place. Has to model\r
+ *                       the ImageView concept and have a pixel type that\r
+ *                       models RGBAPixel.\r
+ */\r
+template<class SrcDstView>\r
+void premultiply(SrcDstView& view_to_modify)\r
+{\r
+       std::for_each(view_to_modify.begin(), view_to_modify.end(), [&](SrcDstView::pixel_type& pixel)\r
+       {\r
+               int alpha = static_cast<int>(pixel.a());\r
+\r
+               if (alpha != 255) // Performance optimization\r
+               {\r
+                       // We don't event try to premultiply 0 since it will be unaffected.\r
+                       if (pixel.r())\r
+                               pixel.r() = static_cast<uint8_t>(static_cast<int>(pixel.r()) * alpha / 255);\r
+\r
+                       if (pixel.g())\r
+                               pixel.g() = static_cast<uint8_t>(static_cast<int>(pixel.g()) * alpha / 255);\r
+\r
+                       if (pixel.b())\r
+                               pixel.b() = static_cast<uint8_t>(static_cast<int>(pixel.b()) * alpha / 255);\r
+               }\r
+       });\r
+}\r
+\r
+}}\r
diff --git a/modules/image/util/image_loader.cpp b/modules/image/util/image_loader.cpp
new file mode 100644 (file)
index 0000000..c876edc
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "image_loader.h"\r
+\r
+#include <common/exception/Exceptions.h>\r
+#include <common/utility/string.h>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#endif\r
+\r
+#include <boost/exception/errinfo_file_name.hpp>\r
+#include <boost/filesystem.hpp>\r
+\r
+namespace caspar { namespace image {\r
+\r
+std::shared_ptr<FIBITMAP> load_image(const std::wstring& filename)\r
+{\r
+       if(!boost::filesystem::exists(filename))\r
+               BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(narrow(filename)));\r
+\r
+       FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;\r
+       fif = FreeImage_GetFileTypeU(filename.c_str(), 0);\r
+       if(fif == FIF_UNKNOWN) \r
+               fif = FreeImage_GetFIFFromFilenameU(filename.c_str());\r
+               \r
+       if(fif == FIF_UNKNOWN || !FreeImage_FIFSupportsReading(fif)) \r
+               BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Unsupported image format."));\r
+               \r
+       auto bitmap = std::shared_ptr<FIBITMAP>(FreeImage_LoadU(fif, filename.c_str(), 0), FreeImage_Unload);\r
+                 \r
+       if(FreeImage_GetBPP(bitmap.get()) != 32)\r
+       {\r
+               bitmap = std::shared_ptr<FIBITMAP>(FreeImage_ConvertTo32Bits(bitmap.get()), FreeImage_Unload);\r
+               if(!bitmap)\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Unsupported image format."));                     \r
+       }\r
+       \r
+       return bitmap;\r
+}\r
+\r
+std::shared_ptr<FIBITMAP> load_image(const std::string& filename)\r
+{\r
+       return load_image(widen(filename));\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/image/util/image_loader.h b/modules/image/util/image_loader.h
new file mode 100644 (file)
index 0000000..face647
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <FreeImage.h>\r
+\r
+#include <memory>\r
+#include <string>\r
+\r
+namespace caspar { namespace image {\r
+\r
+std::shared_ptr<FIBITMAP> load_image(const std::string& filename);\r
+std::shared_ptr<FIBITMAP> load_image(const std::wstring& filename);\r
+\r
+}}\r
diff --git a/modules/image/util/image_view.h b/modules/image/util/image_view.h
new file mode 100644 (file)
index 0000000..422ab3c
--- /dev/null
@@ -0,0 +1,277 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <boost/iterator/filter_iterator.hpp>\r
+\r
+namespace caspar { namespace image {\r
+\r
+/**\r
+ * A POD pixel with a compatible memory layout as a 8bit BGRA pixel (32bits in\r
+ * total).\r
+ * <p>\r
+ * Models the PackedPixel concept used by for example image_view. Also models\r
+ * the RGBAPixel concept which does not care about the order between RGBA but\r
+ * only requires that all 4 channel has accessors.\r
+ */\r
+class bgra_pixel\r
+{\r
+       uint8_t b_;\r
+       uint8_t g_;\r
+       uint8_t r_;\r
+       uint8_t a_;\r
+public:\r
+       bgra_pixel(uint8_t b = 0, uint8_t g = 0, uint8_t r = 0, uint8_t a = 0) : b_(b), g_(g), r_(r), a_(a) {}\r
+       inline const uint8_t& b() const { return b_; }\r
+       inline uint8_t& b() { return b_; }\r
+       inline const uint8_t& g() const { return g_; }\r
+       inline uint8_t& g() { return g_; }\r
+       inline const uint8_t& r() const { return r_; }\r
+       inline uint8_t& r() { return r_; }\r
+       inline const uint8_t& a() const { return a_; }\r
+       inline uint8_t& a() { return a_; }\r
+};\r
+\r
+template<class PackedPixel> class image_sub_view;\r
+\r
+/**\r
+ * An image view abstracting raw packed pixel data\r
+ * <p>\r
+ * This is only a view, it does not own the data.\r
+ * <p>\r
+ * Models the the ImageView concept.\r
+ */\r
+template<class PackedPixel>\r
+class image_view\r
+{\r
+public:\r
+       typedef PackedPixel pixel_type;\r
+\r
+       image_view(void* raw_start, int width, int height)\r
+               : begin_(static_cast<PackedPixel*>(raw_start))\r
+               , end_(begin_ + (width * height))\r
+               , width_(width)\r
+               , height_(height)\r
+       {\r
+       }\r
+\r
+       PackedPixel* begin()\r
+       {\r
+               return begin_;\r
+       }\r
+\r
+       const PackedPixel* begin() const\r
+       {\r
+               return begin_;\r
+       }\r
+\r
+       PackedPixel* end()\r
+       {\r
+               return end_;\r
+       }\r
+\r
+       const PackedPixel* end() const\r
+       {\r
+               return end_;\r
+       }\r
+\r
+       template<class PackedPixelIter>\r
+       inline PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\r
+       {\r
+               auto pixel_distance = delta_x + width_ * delta_y;\r
+               PackedPixel* to_address = &(*to);\r
+               auto result = to_address + pixel_distance;\r
+\r
+               if (result < begin_ || result >= end_)\r
+                       return nullptr;\r
+               else\r
+                       return result;\r
+       }\r
+\r
+       template<class PackedPixelIter>\r
+       inline const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\r
+       {\r
+               //auto x_distance\r
+               auto pixel_distance = delta_x + width_ * delta_y;\r
+               const PackedPixel* to_address = &(*to);\r
+               auto result = to_address + pixel_distance;\r
+\r
+               /*if (delta_x != 0)\r
+               {\r
+                       auto actual_delta_y = result % width_\r
+               }*/\r
+\r
+               if (result < begin_ || result >= end_)\r
+                       return nullptr;\r
+               else\r
+                       return result;\r
+       }\r
+\r
+       int width() const\r
+       {\r
+               return width_;\r
+       }\r
+\r
+       int height() const\r
+       {\r
+               return height_;\r
+       }\r
+\r
+       image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\r
+       {\r
+               return image_sub_view<PackedPixel>(*this, x, y, width, height);\r
+       }\r
+\r
+       const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\r
+       {\r
+               return image_sub_view<PackedPixel>(*this, x, y, width, height);\r
+       }\r
+private:\r
+       PackedPixel* begin_;\r
+       PackedPixel* end_;\r
+       int width_;\r
+       int height_;\r
+};\r
+\r
+template<class PackedPixel>\r
+class is_within_view\r
+{\r
+public:\r
+       is_within_view(const PackedPixel* begin, int width, int stride)\r
+               : begin_(begin)\r
+               , width_(width)\r
+               , stride_(stride)\r
+               , no_check_(width == stride)\r
+       {\r
+       }\r
+\r
+       inline bool operator()(const PackedPixel& pixel) const\r
+       {\r
+               if (no_check_)\r
+                       return true;\r
+\r
+               const PackedPixel* position = &pixel;\r
+               int distance_from_row_start = (position - begin_) % stride_;\r
+\r
+               return distance_from_row_start < width_;\r
+       }\r
+private:\r
+       const PackedPixel* begin_;\r
+       int width_;\r
+       int stride_;\r
+       bool no_check_;\r
+};\r
+\r
+template <class PackedPixel>\r
+struct image_stride_iterator : public boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>\r
+{\r
+       image_stride_iterator(PackedPixel* begin, PackedPixel* end, int width, int stride)\r
+               : boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>::filter_iterator(\r
+                       is_within_view<PackedPixel>(begin, width, stride), begin, end)\r
+       {\r
+       }\r
+};\r
+\r
+/**\r
+ * A sub view created from an image_view.\r
+ * <p>\r
+ * This also models the ImageView concept.\r
+ */\r
+template<class PackedPixel>\r
+class image_sub_view\r
+{\r
+public:\r
+       typedef PackedPixel pixel_type;\r
+\r
+       image_sub_view(image_view<PackedPixel>& root_view, int x, int y, int width, int height)\r
+               : root_view_(root_view)\r
+               , relative_to_root_x_(x)\r
+               , relative_to_root_y_(y)\r
+               , width_(width)\r
+               , height_(height)\r
+               , raw_begin_(root_view.relative(root_view.begin(), x, y))\r
+               , raw_end_(root_view.relative(raw_begin_, width - 1, height_ - 1) + 1)\r
+       {\r
+       }\r
+\r
+       image_stride_iterator<PackedPixel> begin()\r
+       {\r
+               return image_stride_iterator<PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\r
+       }\r
+\r
+       image_stride_iterator<const PackedPixel> begin() const\r
+       {\r
+               return image_stride_iterator<const PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\r
+       }\r
+\r
+       image_stride_iterator<PackedPixel> end()\r
+       {\r
+               return image_stride_iterator<PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\r
+       }\r
+\r
+       image_stride_iterator<const PackedPixel> end() const\r
+       {\r
+               return image_stride_iterator<const PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\r
+       }\r
+\r
+       template<class PackedPixelIter>\r
+       PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\r
+       {\r
+               return root_view_.relative(to, delta_x, delta_y);\r
+       }\r
+\r
+       template<class PackedPixelIter>\r
+       const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\r
+       {\r
+               return root_view_.relative(to, delta_x, delta_y);\r
+       }\r
+\r
+       int width() const\r
+       {\r
+               return width_;\r
+       }\r
+\r
+       int height() const\r
+       {\r
+               return height_;\r
+       }\r
+\r
+       image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\r
+       {\r
+               return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\r
+       }\r
+\r
+       const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\r
+       {\r
+               return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\r
+       }\r
+private:\r
+       image_view<PackedPixel> root_view_;\r
+       int relative_to_root_x_;\r
+       int relative_to_root_y_;\r
+       int width_;\r
+       int height_;\r
+       PackedPixel* raw_begin_;\r
+       PackedPixel* raw_end_;\r
+};\r
+\r
+}}\r
diff --git a/modules/oal/consumer/oal_consumer.cpp b/modules/oal/consumer/oal_consumer.cpp
new file mode 100644 (file)
index 0000000..f1e8a4e
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+* 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: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "oal_consumer.h"
+
+#include <common/exception/exceptions.h>
+#include <common/diagnostics/graph.h>
+#include <common/log/log.h>
+#include <common/utility/timer.h>
+#include <common/utility/string.h>
+#include <common/concurrency/future_util.h>
+
+#include <core/consumer/frame_consumer.h>
+#include <core/mixer/audio/audio_util.h>
+#include <core/video_format.h>
+
+#include <core/mixer/read_frame.h>
+
+#include <SFML/Audio.hpp>
+
+#include <boost/circular_buffer.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/timer.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/optional.hpp>
+
+#include <tbb/concurrent_queue.h>
+
+namespace caspar { namespace oal {
+
+typedef std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>> audio_buffer_16;
+
+struct oal_consumer : public core::frame_consumer,  public sf::SoundStream
+{
+       safe_ptr<diagnostics::graph>                                            graph_;
+       boost::timer                                                                            perf_timer_;
+       int                                                                                                     channel_index_;
+
+       tbb::concurrent_bounded_queue<std::shared_ptr<audio_buffer_16>> input_;
+       boost::circular_buffer<audio_buffer_16>                         container_;
+       tbb::atomic<bool>                                                                       is_running_;
+       core::audio_buffer                                                                      temp;
+
+       core::video_format_desc                                                         format_desc_;
+public:
+       oal_consumer() 
+               : container_(16)
+               , channel_index_(-1)
+       {
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));
+               diagnostics::register_graph(graph_);
+
+               is_running_ = true;
+               input_.set_capacity(1);
+       }
+
+       ~oal_consumer()
+       {
+               is_running_ = false;
+               input_.try_push(std::make_shared<audio_buffer_16>());
+               input_.try_push(std::make_shared<audio_buffer_16>());
+               Stop();
+               input_.try_push(std::make_shared<audio_buffer_16>());
+               input_.try_push(std::make_shared<audio_buffer_16>());
+
+               CASPAR_LOG(info) << print() << L" Successfully Uninitialized."; 
+       }
+
+       // frame consumer
+
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override
+       {
+               format_desc_    = format_desc;          
+               channel_index_  = channel_index;
+               graph_->set_text(print());
+
+               if(Status() != Playing)
+               {
+                       sf::SoundStream::Initialize(2, 48000);
+                       Play();         
+               }
+               CASPAR_LOG(info) << print() << " Sucessfully Initialized.";
+       }
+       
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override
+       {
+               auto buffer = std::make_shared<audio_buffer_16>(core::audio_32_to_16(frame->audio_data()));
+
+               if (!input_.try_push(buffer))
+                       graph_->set_tag("dropped-frame");
+
+
+               return wrap_as_future(is_running_.load());
+       }
+       
+       virtual std::wstring print() const override
+       {
+               return L"oal[" + boost::lexical_cast<std::wstring>(channel_index_) + L"|" + format_desc_.name + L"]";
+       }
+
+       virtual bool has_synchronization_clock() const override
+       {
+               return false;
+       }
+
+       virtual boost::property_tree::wptree info() const override
+       {
+               boost::property_tree::wptree info;
+               info.add(L"type", L"oal-consumer");
+               return info;
+       }
+       
+       virtual size_t buffer_depth() const override
+       {
+               return 6;
+       }
+
+       // oal_consumer
+       
+       virtual bool OnGetData(sf::SoundStream::Chunk& data) override
+       {               
+               std::shared_ptr<audio_buffer_16> audio_data;            
+
+               if (!input_.try_pop(audio_data))
+               {
+                       graph_->set_tag("late-frame");
+                       input_.pop(audio_data); // Block until available
+               }
+
+               container_.push_back(std::move(*audio_data));
+               data.Samples = container_.back().data();
+               data.NbSamples = container_.back().size();      
+               
+               graph_->set_value("tick-time", perf_timer_.elapsed()*format_desc_.fps*0.5);             
+               perf_timer_.restart();
+
+               return is_running_;
+       }
+
+       virtual int index() const override
+       {
+               return 500;
+       }
+};
+
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)
+{
+       if(params.size() < 1 || params[0] != L"AUDIO")
+               return core::frame_consumer::empty();
+
+       return make_safe<oal_consumer>();
+}
+
+safe_ptr<core::frame_consumer> create_consumer()
+{
+       return make_safe<oal_consumer>();
+}
+
+}}
diff --git a/modules/oal/consumer/oal_consumer.h b/modules/oal/consumer/oal_consumer.h
new file mode 100644 (file)
index 0000000..6d8dd04
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <vector>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+}      \r
+\r
+namespace oal {\r
+       \r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_consumer> create_consumer();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/oal/oal.cpp b/modules/oal/oal.cpp
new file mode 100644 (file)
index 0000000..696fe3e
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "oal.h"\r
+\r
+#include "consumer/oal_consumer.h"\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+namespace caspar { namespace oal {\r
+\r
+void init()\r
+{\r
+       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/oal/oal.h b/modules/oal/oal.h
new file mode 100644 (file)
index 0000000..5bf9124
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar { namespace oal {\r
+\r
+void init();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/oal/oal.vcxproj b/modules/oal/oal.vcxproj
new file mode 100644 (file)
index 0000000..9b77c13
--- /dev/null
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}</ProjectGuid>\r
+    <RootNamespace>oal</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>oal</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\oal_consumer.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="oal.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\oal_consumer.h" />\r
+    <ClInclude Include="oal.h" />\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/oal/oal.vcxproj.filters b/modules/oal/oal.vcxproj.filters
new file mode 100644 (file)
index 0000000..58ad5f5
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{c40c13eb-e8ef-4528-8972-fa108b0d0ed0}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{2de4befc-0e04-496c-be98-83b7d4a76e8a}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\oal_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="oal.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\oal_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="oal.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/ogl/consumer/ogl_consumer.cpp b/modules/ogl/consumer/ogl_consumer.cpp
new file mode 100644 (file)
index 0000000..f381363
--- /dev/null
@@ -0,0 +1,629 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "ogl_consumer.h"\r
+\r
+#include <GL/glew.h>\r
+#include <SFML/Window.hpp>\r
+\r
+#include <common/diagnostics/graph.h>\r
+#include <common/gl/gl_check.h>\r
+#include <common/log/log.h>\r
+#include <common/memory/safe_ptr.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/memory/memshfl.h>\r
+#include <common/utility/timer.h>\r
+#include <common/utility/string.h>\r
+#include <common/concurrency/future_util.h>\r
+\r
+#include <ffmpeg/producer/filter/filter.h>\r
+\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+#include <boost/timer.hpp>\r
+#include <boost/circular_buffer.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/assign.hpp>\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
+extern "C" \r
+{\r
+       #define __STDC_CONSTANT_MACROS\r
+       #define __STDC_LIMIT_MACROS\r
+       #include <libavcodec/avcodec.h>\r
+       #include <libavutil/imgutils.h>\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
+\r
+typedef int (*PFNWGLEXTGETSWAPINTERVALPROC) (void);\r
\r
+namespace caspar { namespace ogl {\r
+               \r
+enum stretch\r
+{\r
+       none,\r
+       uniform,\r
+       fill,\r
+       uniform_to_fill\r
+};\r
+\r
+struct configuration\r
+{\r
+       enum aspect_ratio\r
+       {\r
+               aspect_4_3 = 0,\r
+               aspect_16_9,\r
+               aspect_invalid,\r
+       };\r
+               \r
+       std::wstring    name;\r
+       size_t                  screen_index;\r
+       stretch                 stretch;\r
+       bool                    windowed;\r
+       bool                    auto_deinterlace;\r
+       bool                    key_only;\r
+       aspect_ratio    aspect; \r
+       bool                    vsync;\r
+\r
+       configuration()\r
+               : name(L"ogl")\r
+               , screen_index(0)\r
+               , stretch(fill)\r
+               , windowed(true)\r
+               , auto_deinterlace(true)\r
+               , key_only(false)\r
+               , aspect(aspect_invalid)\r
+               , vsync(false)\r
+       {\r
+       }\r
+};\r
+\r
+struct ogl_consumer : boost::noncopyable\r
+{              \r
+       const configuration             config_;\r
+       core::video_format_desc format_desc_;\r
+       int                                             channel_index_;\r
+\r
+       GLuint                                  texture_;\r
+       std::vector<GLuint>             pbos_;\r
+                       \r
+       float                                   width_;\r
+       float                                   height_;        \r
+       unsigned int                    screen_x_;\r
+       unsigned int                    screen_y_;\r
+       unsigned int                    screen_width_;\r
+       unsigned int                    screen_height_;\r
+       size_t                                  square_width_;\r
+       size_t                                  square_height_;                         \r
+       \r
+       sf::Window                              window_;\r
+       \r
+       safe_ptr<diagnostics::graph>    graph_;\r
+       boost::timer                                    perf_timer_;\r
+       boost::timer                                    tick_timer_;\r
+\r
+       caspar::high_prec_timer wait_timer_;\r
+\r
+       tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>>       frame_buffer_;\r
+\r
+       boost::thread                   thread_;\r
+       tbb::atomic<bool>               is_running_;\r
+       \r
+       ffmpeg::filter                  filter_;\r
+public:\r
+       ogl_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index) \r
+               : config_(config)\r
+               , format_desc_(format_desc)\r
+               , channel_index_(channel_index)\r
+               , texture_(0)\r
+               , pbos_(2, 0)   \r
+               , screen_width_(format_desc.width)\r
+               , screen_height_(format_desc.height)\r
+               , square_width_(format_desc.square_width)\r
+               , square_height_(format_desc.square_height)\r
+               , filter_(format_desc.field_mode == core::field_mode::progressive || !config.auto_deinterlace ? L"" : L"YADIF=1:-1", boost::assign::list_of(PIX_FMT_BGRA))\r
+       {               \r
+               if(format_desc_.format == core::video_format::ntsc && config_.aspect == configuration::aspect_4_3)\r
+               {\r
+                       // Use default values which are 4:3.\r
+               }\r
+               else\r
+               {\r
+                       if(config_.aspect == configuration::aspect_16_9)\r
+                               square_width_ = (format_desc.height*16)/9;\r
+                       else if(config_.aspect == configuration::aspect_4_3)\r
+                               square_width_ = (format_desc.height*4)/3;\r
+               }\r
+\r
+               frame_buffer_.set_capacity(2);\r
+               \r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
+               graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+                                                                       \r
+               DISPLAY_DEVICE d_device = {sizeof(d_device), 0};                        \r
+               std::vector<DISPLAY_DEVICE> displayDevices;\r
+               for(int n = 0; EnumDisplayDevices(NULL, n, &d_device, NULL); ++n)\r
+                       displayDevices.push_back(d_device);\r
+\r
+               if(config_.screen_index >= displayDevices.size())\r
+                       CASPAR_LOG(warning) << print() << L" Invalid screen-index: " << config_.screen_index;\r
+               \r
+               DEVMODE devmode = {};\r
+               if(!EnumDisplaySettings(displayDevices[config_.screen_index].DeviceName, ENUM_CURRENT_SETTINGS, &devmode))\r
+                       CASPAR_LOG(warning) << print() << L" Could not find display settings for screen-index: " << config_.screen_index;\r
+               \r
+               screen_x_               = devmode.dmPosition.x;\r
+               screen_y_               = devmode.dmPosition.y;\r
+               screen_width_   = config_.windowed ? square_width_ : devmode.dmPelsWidth;\r
+               screen_height_  = config_.windowed ? square_height_ : devmode.dmPelsHeight;\r
+\r
+               is_running_ = true;\r
+               thread_ = boost::thread([this]{run();});\r
+       }\r
+       \r
+       ~ogl_consumer()\r
+       {\r
+               is_running_ = false;\r
+               frame_buffer_.try_push(make_safe<core::read_frame>());\r
+               thread_.join();\r
+       }\r
+\r
+       void init()\r
+       {\r
+               if(!GLEW_VERSION_2_1)\r
+                       BOOST_THROW_EXCEPTION(not_supported() << msg_info("Missing OpenGL 2.1 support."));\r
+\r
+               window_.Create(sf::VideoMode(screen_width_, screen_height_, 32), narrow(L"Screen consumer " + channel_and_format()), config_.windowed ? sf::Style::Resize | sf::Style::Close : sf::Style::Fullscreen);\r
+               window_.ShowMouseCursor(false);\r
+               window_.SetPosition(screen_x_, screen_y_);\r
+               window_.SetSize(screen_width_, screen_height_);\r
+               window_.SetActive();\r
+               GL(glEnable(GL_TEXTURE_2D));\r
+               GL(glDisable(GL_DEPTH_TEST));           \r
+               GL(glClearColor(0.0, 0.0, 0.0, 0.0));\r
+               GL(glViewport(0, 0, format_desc_.width, format_desc_.height));\r
+               GL(glLoadIdentity());\r
+                               \r
+               calculate_aspect();\r
+                       \r
+               GL(glGenTextures(1, &texture_));\r
+               GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
+               GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
+               GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
+               GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));\r
+               GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));\r
+               GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, format_desc_.width, format_desc_.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0));\r
+               GL(glBindTexture(GL_TEXTURE_2D, 0));\r
+                                       \r
+               GL(glGenBuffers(2, pbos_.data()));\r
+                       \r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[0]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[1]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);\r
+                               \r
+               if(config_.vsync)\r
+               {\r
+                       auto wglSwapIntervalEXT = reinterpret_cast<void(APIENTRY*)(int)>(wglGetProcAddress("wglSwapIntervalEXT"));\r
+                       if(wglSwapIntervalEXT)\r
+                       {\r
+                               wglSwapIntervalEXT(1);\r
+                               CASPAR_LOG(info) << print() << " Successfully enabled vsync.";\r
+                       }\r
+                       else\r
+                               CASPAR_LOG(info) << print() << " Failed to enable vsync.";\r
+               }\r
+\r
+               CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
+       }\r
+\r
+       void uninit()\r
+       {               \r
+               if(texture_)\r
+                       glDeleteTextures(1, &texture_);\r
+\r
+               BOOST_FOREACH(auto& pbo, pbos_)\r
+               {\r
+                       if(pbo)\r
+                               glDeleteBuffers(1, &pbo);\r
+               }\r
+       }\r
+\r
+       void run()\r
+       {\r
+               try\r
+               {\r
+                       init();\r
+\r
+                       while(is_running_)\r
+                       {                       \r
+                               try\r
+                               {\r
+\r
+                                       sf::Event e;            \r
+                                       while(window_.GetEvent(e))\r
+                                       {\r
+                                               if(e.Type == sf::Event::Resized)\r
+                                                       calculate_aspect();\r
+                                               else if(e.Type == sf::Event::Closed)\r
+                                                       is_running_ = false;\r
+                                       }\r
+                       \r
+                                       safe_ptr<core::read_frame> frame;\r
+\r
+                                       frame_buffer_.pop(frame);\r
+\r
+                                       render_and_draw_frame(frame);\r
+                                       \r
+                                       graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);     \r
+                                       tick_timer_.restart();\r
+                               }\r
+                               catch(...)\r
+                               {\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                       is_running_ = false;\r
+                               }\r
+                       }\r
+\r
+                       uninit();\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+\r
+       void try_sleep_almost_until_vblank()\r
+       {\r
+               static const double THRESHOLD = 0.003;\r
+               double threshold = config_.vsync ? THRESHOLD : 0.0;\r
+\r
+               auto frame_time = 1.0 / (format_desc_.fps * format_desc_.field_count);\r
+\r
+               wait_timer_.tick(frame_time - threshold);\r
+       }\r
+\r
+       void wait_for_vblank_and_display()\r
+       {\r
+               try_sleep_almost_until_vblank();\r
+               window_.Display();\r
+               // Make sure that the next tick measures the duration from this point in time.\r
+               wait_timer_.tick(0.0);\r
+       }\r
+       \r
+       safe_ptr<AVFrame> get_av_frame()\r
+       {               \r
+               safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);     \r
+               avcodec_get_frame_defaults(av_frame.get());\r
+                                               \r
+               av_frame->linesize[0]           = format_desc_.width*4;                 \r
+               av_frame->format                        = PIX_FMT_BGRA;\r
+               av_frame->width                         = format_desc_.width;\r
+               av_frame->height                        = format_desc_.height;\r
+               av_frame->interlaced_frame      = format_desc_.field_mode != core::field_mode::progressive;\r
+               av_frame->top_field_first       = format_desc_.field_mode == core::field_mode::upper ? 1 : 0;\r
+\r
+               return av_frame;\r
+       }\r
+\r
+       void render_and_draw_frame(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               if(static_cast<size_t>(frame->image_data().size()) != format_desc_.size)\r
+                       return;\r
+                                       \r
+               perf_timer_.restart();\r
+               auto av_frame = get_av_frame();\r
+               av_frame->data[0] = const_cast<uint8_t*>(frame->image_data().begin());\r
+\r
+               filter_.push(av_frame);\r
+               auto frames = filter_.poll_all();\r
+\r
+               if (frames.empty())\r
+                       return;\r
+\r
+               if (frames.size() == 1)\r
+               {\r
+                       render(frames[0], frame->image_data().size());\r
+                       graph_->set_value("frame-time", perf_timer_.elapsed() * format_desc_.fps * 0.5);\r
+\r
+                       wait_for_vblank_and_display(); // progressive frame\r
+               }\r
+               else if (frames.size() == 2)\r
+               {\r
+                       render(frames[0], frame->image_data().size());\r
+                       double perf_elapsed = perf_timer_.elapsed();\r
+\r
+                       wait_for_vblank_and_display(); // field1\r
+\r
+                       perf_timer_.restart();\r
+                       render(frames[1], frame->image_data().size());\r
+                       perf_elapsed += perf_timer_.elapsed();\r
+                       graph_->set_value("frame-time", perf_elapsed * format_desc_.fps * 0.5);\r
+\r
+                       wait_for_vblank_and_display(); // field2\r
+               }\r
+       }\r
+\r
+       void render(safe_ptr<AVFrame> av_frame, int image_data_size)\r
+       {\r
+               if(av_frame->linesize[0] != static_cast<int>(format_desc_.width*4))\r
+               {\r
+                       const uint8_t *src_data[4] = {0};\r
+                       memcpy(const_cast<uint8_t**>(&src_data[0]), av_frame->data, 4);\r
+                       const int src_linesizes[4] = {0};\r
+                       memcpy(const_cast<int*>(&src_linesizes[0]), av_frame->linesize, 4);\r
+\r
+                       auto av_frame2 = get_av_frame();\r
+                       av_image_alloc(av_frame2->data, av_frame2->linesize, av_frame2->width, av_frame2->height, PIX_FMT_BGRA, 16);\r
+                       av_frame = safe_ptr<AVFrame>(av_frame2.get(), [=](AVFrame*)\r
+                       {\r
+                               av_freep(&av_frame2->data[0]);\r
+                       });\r
+\r
+                       av_image_copy(av_frame2->data, av_frame2->linesize, src_data, src_linesizes, PIX_FMT_BGRA, av_frame2->width, av_frame2->height);\r
+               }\r
+\r
+               glBindTexture(GL_TEXTURE_2D, texture_);\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[0]);\r
+               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[1]);\r
+               glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, 0, GL_STREAM_DRAW);\r
+\r
+               auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
+               if(ptr)\r
+               {\r
+                       if(config_.key_only)\r
+                               fast_memshfl(reinterpret_cast<char*>(ptr), av_frame->data[0], image_data_size, 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                       else\r
+                               fast_memcpy(reinterpret_cast<char*>(ptr), av_frame->data[0], image_data_size);\r
+\r
+                       glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer\r
+               }\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);\r
+                               \r
+               GL(glClear(GL_COLOR_BUFFER_BIT));                       \r
+               glBegin(GL_QUADS);\r
+                               glTexCoord2f(0.0f,        1.0f);        glVertex2f(-width_, -height_);\r
+                               glTexCoord2f(1.0f,        1.0f);        glVertex2f( width_, -height_);\r
+                               glTexCoord2f(1.0f,        0.0f);        glVertex2f( width_,  height_);\r
+                               glTexCoord2f(0.0f,        0.0f);        glVertex2f(-width_,  height_);\r
+               glEnd();\r
+               \r
+               glBindTexture(GL_TEXTURE_2D, 0);\r
+\r
+               std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
+       }\r
+\r
+       boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame)\r
+       {\r
+               if (!frame_buffer_.try_push(frame))\r
+                       graph_->set_tag("dropped-frame"); \r
+\r
+               return wrap_as_future(is_running_.load());\r
+       }\r
+\r
+       std::wstring channel_and_format() const\r
+       {\r
+               return L"[" + boost::lexical_cast<std::wstring>(channel_index_) + L"|" + format_desc_.name + L"]";\r
+       }\r
+               \r
+       std::wstring print() const\r
+       {       \r
+               return config_.name + channel_and_format();\r
+       }\r
+       \r
+       void calculate_aspect()\r
+       {\r
+               if(config_.windowed)\r
+               {\r
+                       screen_height_ = window_.GetHeight();\r
+                       screen_width_ = window_.GetWidth();\r
+               }\r
+               \r
+               GL(glViewport(0, 0, screen_width_, screen_height_));\r
+\r
+               std::pair<float, float> target_ratio = None();\r
+               if(config_.stretch == fill)\r
+                       target_ratio = Fill();\r
+               else if(config_.stretch == uniform)\r
+                       target_ratio = Uniform();\r
+               else if(config_.stretch == uniform_to_fill)\r
+                       target_ratio = UniformToFill();\r
+\r
+               width_ = target_ratio.first;\r
+               height_ = target_ratio.second;\r
+       }\r
+               \r
+       std::pair<float, float> None()\r
+       {\r
+               float width = static_cast<float>(square_width_)/static_cast<float>(screen_width_);\r
+               float height = static_cast<float>(square_height_)/static_cast<float>(screen_height_);\r
+\r
+               return std::make_pair(width, height);\r
+       }\r
+\r
+       std::pair<float, float> Uniform()\r
+       {\r
+               float aspect = static_cast<float>(square_width_)/static_cast<float>(square_height_);\r
+               float width = std::min(1.0f, static_cast<float>(screen_height_)*aspect/static_cast<float>(screen_width_));\r
+               float height = static_cast<float>(screen_width_*width)/static_cast<float>(screen_height_*aspect);\r
+\r
+               return std::make_pair(width, height);\r
+       }\r
+\r
+       std::pair<float, float> Fill()\r
+       {\r
+               return std::make_pair(1.0f, 1.0f);\r
+       }\r
+\r
+       std::pair<float, float> UniformToFill()\r
+       {\r
+               float wr = static_cast<float>(square_width_)/static_cast<float>(screen_width_);\r
+               float hr = static_cast<float>(square_height_)/static_cast<float>(screen_height_);\r
+               float r_inv = 1.0f/std::min(wr, hr);\r
+\r
+               float width = wr*r_inv;\r
+               float height = hr*r_inv;\r
+\r
+               return std::make_pair(width, height);\r
+       }\r
+};\r
+\r
+\r
+struct ogl_consumer_proxy : public core::frame_consumer\r
+{\r
+       const configuration config_;\r
+       std::unique_ptr<ogl_consumer> consumer_;\r
+\r
+public:\r
+\r
+       ogl_consumer_proxy(const configuration& config)\r
+               : config_(config){}\r
+       \r
+       ~ogl_consumer_proxy()\r
+       {\r
+               if(consumer_)\r
+               {\r
+                       auto str = print();\r
+                       consumer_.reset();\r
+                       CASPAR_LOG(info) << str << L" Successfully Uninitialized.";     \r
+               }\r
+       }\r
+\r
+       // frame_consumer\r
+\r
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               consumer_.reset();\r
+               consumer_.reset(new ogl_consumer(config_, format_desc, channel_index));\r
+               CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
+       }\r
+       \r
+       virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override\r
+       {\r
+               return consumer_->send(frame);\r
+       }\r
+       \r
+       virtual std::wstring print() const override\r
+       {\r
+               return consumer_ ? consumer_->print() : L"[ogl_consumer]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"ogl-consumer");\r
+               info.add(L"key-only", config_.key_only);\r
+               info.add(L"windowed", config_.windowed);\r
+               info.add(L"auto-deinterlace", config_.auto_deinterlace);\r
+               return info;\r
+       }\r
+\r
+       virtual bool has_synchronization_clock() const override\r
+       {\r
+               return false;\r
+       }\r
+       \r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return 1;\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 600 + config_.screen_index;\r
+       }\r
+};     \r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 1 || params[0] != L"SCREEN")\r
+               return core::frame_consumer::empty();\r
+       \r
+       configuration config;\r
+               \r
+       if(params.size() > 1)\r
+               config.screen_index = lexical_cast_or_default<int>(params[1], config.screen_index);\r
+\r
+       auto device_it = std::find(params.begin(), params.end(), L"DEVICE");\r
+       if(device_it != params.end() && ++device_it != params.end())\r
+               config.screen_index = boost::lexical_cast<int>(*device_it);\r
+               \r
+       config.windowed = std::find(params.begin(), params.end(), L"FULLSCREEN") == params.end();\r
+       config.key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
+\r
+       auto name_it    = std::find(params.begin(), params.end(), L"NAME");\r
+       if(name_it != params.end() && ++name_it != params.end())\r
+               config.name = *name_it;\r
+\r
+       return make_safe<ogl_consumer_proxy>(config);\r
+}\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree) \r
+{\r
+       configuration config;\r
+       config.name                             = ptree.get(L"name",     config.name);\r
+       config.screen_index             = ptree.get(L"device",   config.screen_index+1)-1;\r
+       config.windowed                 = ptree.get(L"windowed", config.windowed);\r
+       config.key_only                 = ptree.get(L"key-only", config.key_only);\r
+       config.auto_deinterlace = ptree.get(L"auto-deinterlace", config.auto_deinterlace);\r
+       config.vsync                    = ptree.get(L"vsync", config.vsync);\r
+\r
+       auto stretch_str = ptree.get(L"stretch", L"default");\r
+       if(stretch_str == L"uniform")\r
+               config.stretch = stretch::uniform;\r
+       else if(stretch_str == L"uniform_to_fill")\r
+               config.stretch = stretch::uniform_to_fill;\r
+\r
+       auto aspect_str = ptree.get(L"aspect-ratio", L"default");\r
+       if(aspect_str == L"16:9")\r
+               config.aspect = configuration::aspect_16_9;\r
+       else if(aspect_str == L"4:3")\r
+               config.aspect = configuration::aspect_4_3;\r
+       \r
+       return make_safe<ogl_consumer_proxy>(config);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ogl/consumer/ogl_consumer.h b/modules/ogl/consumer/ogl_consumer.h
new file mode 100644 (file)
index 0000000..611e8f6
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <vector>\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+namespace caspar { \r
+       \r
+namespace core {\r
+       struct frame_consumer;\r
+}\r
+\r
+namespace ogl {\r
+\r
+\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptree& ptree);\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ogl/ogl.cpp b/modules/ogl/ogl.cpp
new file mode 100644 (file)
index 0000000..ab3086d
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "ogl.h"\r
+\r
+#include "consumer/ogl_consumer.h"\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+\r
+namespace caspar { namespace ogl {\r
+\r
+void init()\r
+{\r
+       caspar::core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ogl/ogl.h b/modules/ogl/ogl.h
new file mode 100644 (file)
index 0000000..bd928d1
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+namespace caspar { namespace ogl {\r
+\r
+void init();\r
+\r
+}}
\ No newline at end of file
diff --git a/modules/ogl/ogl.vcxproj b/modules/ogl/ogl.vcxproj
new file mode 100644 (file)
index 0000000..b9e33c6
--- /dev/null
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{88F974F0-D09F-4788-8CF8-F563209E60C1}</ProjectGuid>\r
+    <RootNamespace>ogl</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>ogl</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\glew-1.6.0\include;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\ffmpeg 0.8\include;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\glew-1.6.0\include;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\ffmpeg 0.8\include;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\glew-1.6.0\include;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\ffmpeg 0.8\include;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\glew-1.6.0\include;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include;..\..\dependencies\ffmpeg 0.8\include;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>sfml-window.lib;sfml-graphics.lib;OpenGL32.lib;tbb.lib;Glee.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>true</GenerateMapFile>\r
+      <MapExports>true</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\ffmpeg\ffmpeg.vcxproj">\r
+      <Project>{f6223af3-be0b-4b61-8406-98922ce521c2}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\ogl_consumer.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="ogl.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\ogl_consumer.h" />\r
+    <ClInclude Include="ogl.h" />\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/ogl/ogl.vcxproj.filters b/modules/ogl/ogl.vcxproj.filters
new file mode 100644 (file)
index 0000000..3581021
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{17d30d8e-4f28-410d-b8f9-ce880259b11a}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{013ef3ed-0241-481f-b887-a54e4749045f}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="consumer\ogl_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="ogl.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="consumer\ogl_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="ogl.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/silverlight/StdAfx.cpp b/modules/silverlight/StdAfx.cpp
new file mode 100644 (file)
index 0000000..2bd615b
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
\r
+// stdafx.cpp : source file that includes just the standard includes\r
+//     dma.pch will be the pre-compiled header\r
+//     stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
diff --git a/modules/silverlight/StdAfx.h b/modules/silverlight/StdAfx.h
new file mode 100644 (file)
index 0000000..75da809
--- /dev/null
@@ -0,0 +1,83 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
\r
+// stdafx.h : include file for standard system include files,\r
+//  or project specific include files that are used frequently, but\r
+//      are changed infrequently\r
+//\r
+\r
+#pragma once\r
+\r
+#include "../common/compiler/vs/disable_silly_warnings.h"\r
+\r
+#define NOMINMAX\r
+\r
+#if defined(_MSC_VER)\r
+#      ifndef _SCL_SECURE_NO_WARNINGS\r
+#              define _SCL_SECURE_NO_WARNINGS\r
+#      endif\r
+#      ifndef _CRT_SECURE_NO_WARNINGS\r
+#              define _CRT_SECURE_NO_WARNINGS\r
+#      endif\r
+#endif\r
+\r
+#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
+#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
+\r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#include <memory>\r
+#include <array>\r
+#include <functional>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <deque>\r
+#include <queue>\r
+#include <string>\r
+#include <math.h>\r
+\r
+#include <tbb/atomic.h>\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/concurrent_unordered_map.h>\r
+#include <tbb/parallel_invoke.h>\r
+#include <tbb/parallel_for.h>\r
+#include <tbb/parallel_for_each.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+#include <boost/signals2.hpp>\r
+\r
+#include "../common/utility/string.h"\r
+#include "../common/memory/safe_ptr.h"\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include "../common/log/Log.h"\r
+#include "../common/exception/exceptions.h"\r
+#include "../common/exception/win32_exception.h"\r
+\r
+#include <assert.h>\r
+\r
+#endif\r
diff --git a/modules/silverlight/interop/XcpControlHost.cpp b/modules/silverlight/interop/XcpControlHost.cpp
new file mode 100644 (file)
index 0000000..f2b34c6
--- /dev/null
@@ -0,0 +1,308 @@
+#include "../StdAfx.h"\r
+\r
+#include "XcpControlHost.h"\r
+#include "XcpPropertyBag.h"\r
+#include "Ocidl.h"\r
+#include "xcpctrl_h.h"\r
+\r
+#include "atlstr.h"\r
+\r
+using namespace ATL;\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning (disable : 4100)\r
+#pragma warning(disable:4061)\r
+#endif\r
+\r
+XcpControlHost::XcpControlHost() \r
+       : hControlWindow(nullptr)\r
+       , m_pUnKnown(nullptr)\r
+       , m_pControl(nullptr)\r
+{\r
+}\r
+\r
+XcpControlHost::~XcpControlHost() \r
+{\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::GetHostOptions(DWORD* pdwOptions)\r
+{\r
+       *pdwOptions = XcpHostOption_EnableCrossDomainDownloads|\r
+               XcpHostOption_EnableScriptableObjectAccess|XcpHostOption_EnableHtmlDomAccess;\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::GetCustomAppDomain(IUnknown** ppAppDomain) \r
+{  \r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::GetControlVersion(UINT *puMajorVersion, UINT *puMinorVersion)\r
+{\r
+       *puMajorVersion = 4;\r
+       *puMinorVersion = 50401;\r
+       return S_OK;;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::NotifyLoaded() \r
+{\r
+//     MessageBox(L"Notify Loaded", L"Silverlight Error", 0);\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::NotifyError(BSTR bstrError, BSTR bstrSource, long nLine, long nColumn)\r
+{\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::InvokeHandler(BSTR bstrName, VARIANT varParam1, VARIANT varParam2, VARIANT* pvarResult) \r
+{\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::GetBaseUrl(BSTR* pbstrUrl) {\r
+\r
+       CAtlString strPath = "C:\\";\r
+       //TCHAR pBuff[255];\r
+       //GetCurrentDirectory(255, pBuff);\r
+       //strPath = pBuff;\r
+       //strPath += "\\";\r
+\r
+       *pbstrUrl = SysAllocString(strPath);\r
+\r
+       //MessageBox(*pbstrUrl, L"GetBaseUrl", 0);\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::GetNamedSource(BSTR bstrSourceName, BSTR* pbstrSource) \r
+{    \r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP XcpControlHost::DownloadUrl(BSTR bstrUrl, IXcpControlDownloadCallback* pCallback, IStream** ppStream) \r
+{\r
+//     MessageBox(L"DownloadUrl", L"DownloadUrl", 0);\r
+       return S_FALSE;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// XcpControlHost IServiceProvider Implementation\r
+\r
+STDMETHODIMP XcpControlHost::QueryService(REFGUID rsid, REFIID riid, void** ppvObj) {\r
+       ATLASSERT(ppvObj != NULL);\r
+       if (ppvObj == NULL)\r
+               return E_POINTER;\r
+       *ppvObj = NULL;\r
+\r
+       //static const GUID IID_IXcpControlHost = \r
+       //      { 0x1B36028E, 0xB491, 0x4bb2, { 0x85, 0x84, 0x8A, 0x9E, 0x0A, 0x67, 0x7D, 0x6E }};\r
+\r
+       HRESULT hr = E_NOINTERFACE;\r
+\r
+       if ((rsid == IID_IXcpControlHost) && (riid == IID_IXcpControlHost)) {\r
+               ((IXcpControlHost*)this)->AddRef();\r
+               *ppvObj = (IXcpControlHost*)this;\r
+               hr = S_OK;\r
+       }\r
+\r
+       if ((rsid == IID_IXcpControlHost2) && (riid == IID_IXcpControlHost2)) {\r
+               ((IXcpControlHost2*)this)->AddRef();\r
+               *ppvObj = (IXcpControlHost2*)this;\r
+               hr = S_OK;\r
+       }\r
+\r
+\r
+       return hr;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// General ActiveX control embedding.\r
+\r
+\r
+HRESULT XcpControlHost::CreateXcpControl(HWND hWnd) \r
+{\r
+       AtlAxWinInit();\r
+\r
+       HRESULT hr;\r
+       static const GUID IID_IXcpControl = \r
+               { 0x1FB839CC, 0x116C, 0x4C9B, { 0xAE, 0x8E, 0x3D, 0xBB, 0x64, 0x96, 0xE3, 0x26 }};\r
+\r
+       static const GUID CLSID_XcpControl = \r
+               { 0xDFEAF541, 0xF3E1, 0x4c24, { 0xAC, 0xAC, 0x99, 0xC3, 0x07, 0x15, 0x08, 0x4A }};\r
+\r
+       static const GUID IID_IXcpControl2 = \r
+               { 0x1c3294f9, 0x891f, 0x49b1, { 0xBB, 0xAE, 0x49, 0x2a, 0x68, 0xBA, 0x10, 0xcc }};\r
+\r
+//     static const GUID CLSID_XcpControl2 = \r
+//             { 0xDFEAF541, 0xF3E1, 0x4c24, { 0xAC, 0xAC, 0x99, 0xC3, 0x07, 0x15, 0x08, 0x4A }};\r
+\r
+       //static const GUID IID_IXcpControlHost2 = \r
+       //      { 0xfb3ed7c4, 0x5797, 0x4b44, { 0x86, 0x95, 0x0c, 0x51, 0x2e, 0xa2, 0x7D, 0x8f }};\r
+       \r
+       hr = CoCreateInstance(CLSID_XcpControl, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_pUnKnown);\r
+       \r
+       if (SUCCEEDED(hr)) \r
+       {\r
+               CComPtr<IUnknown> spUnkContainer;\r
+               hr = XcpControlHost::_CreatorClass::CreateInstance(NULL, IID_IUnknown, (void**)&spUnkContainer);\r
+               if (SUCCEEDED(hr)) \r
+               {\r
+                       CComPtr<IAxWinHostWindow> pAxWindow;\r
+\r
+                       spUnkContainer->QueryInterface(IID_IAxWinHostWindow, (void**)&pAxWindow);\r
+                       m_pUnKnown->QueryInterface(IID_IXcpControl2, (void**)&m_pControl);\r
+                       hr = pAxWindow->AttachControl(m_pUnKnown, hWnd);            \r
+                       hControlWindow = hWnd;\r
+\r
+                       IOleInPlaceActiveObject *pObj;\r
+                       hr = m_pControl->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&pObj);\r
+               }\r
+       }\r
+       return hr;\r
+}\r
+\r
+HRESULT XcpControlHost::DestroyXcpControl()\r
+{\r
+       HRESULT hr = S_OK;\r
+       if (m_pControl)\r
+       {\r
+               m_pControl->Release();\r
+       }\r
+       if (m_pUnKnown)\r
+       {\r
+               m_pUnKnown->Release();\r
+       }\r
+       return hr;\r
+}\r
+\r
+\r
+STDMETHODIMP XcpControlHost::AttachControl(IUnknown* pUnKnown, HWND hWnd) {\r
+       ReleaseAll();\r
+\r
+       HRESULT hr = S_FALSE;\r
+       BOOL fReleaseWindowOnFailure = FALSE;\r
+\r
+       if ((m_hWnd != NULL) && (m_hWnd != hWnd)) {\r
+               // Don't release the window if it's the same as the one we already subclass/own\r
+               RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);\r
+               ReleaseWindow();\r
+       }\r
+\r
+       if (::IsWindow(hWnd)) {\r
+               if (m_hWnd != hWnd) {\r
+                       // Don't need to subclass the window if we already own it\r
+                       SubclassWindow(hWnd);\r
+                       fReleaseWindowOnFailure = TRUE;\r
+               }\r
+\r
+               hr = ActivateXcpControl(pUnKnown);\r
+               if (FAILED(hr)) {\r
+                       ReleaseAll();\r
+\r
+                       if (m_hWnd != NULL) {\r
+                               RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);\r
+\r
+                               if (fReleaseWindowOnFailure) {\r
+                                       // We subclassed the window in an attempt to create this control, so we unsubclass on failure\r
+                                       ReleaseWindow();\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       return hr;\r
+}\r
+\r
+HRESULT XcpControlHost::ActivateXcpControl(IUnknown* pUnKnown) \r
+{\r
+       if (pUnKnown == NULL)\r
+       {\r
+               return S_OK;\r
+       }\r
+\r
+       m_spUnknown = pUnKnown;\r
+\r
+       HRESULT hr = S_OK;\r
+       pUnKnown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);\r
+       if (m_spOleObject) \r
+       {\r
+               m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);\r
+               if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) \r
+               {\r
+                       CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                       m_spOleObject->SetClientSite(spClientSite);\r
+               }\r
+\r
+               CComQIPtr<IPersistPropertyBag> pPersist(m_spOleObject);\r
+\r
+               if (pPersist != NULL) \r
+               {\r
+                       IPropertyBag* pPropBag = new XcpPropertyBag();\r
+                       pPropBag->AddRef();\r
+\r
+                       pPersist->Load((IPropertyBag*)pPropBag, NULL);\r
+                       pPropBag->Release();\r
+               }\r
+\r
+               if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) \r
+               {\r
+                       CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                       m_spOleObject->SetClientSite(spClientSite);\r
+               }\r
+\r
+               m_dwViewObjectType = 0;\r
+               hr = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);\r
+               if (FAILED(hr)) \r
+               {\r
+                       hr = m_spOleObject->QueryInterface(__uuidof(IViewObject2), (void**) &m_spViewObject);\r
+                       if (SUCCEEDED(hr)) {\r
+                               m_dwViewObjectType = 3;\r
+                       }\r
+               }\r
+               else {\r
+                       m_dwViewObjectType = 7;\r
+               }\r
+\r
+               if (FAILED(hr)) \r
+               {\r
+                       hr = m_spOleObject->QueryInterface(__uuidof(IViewObject), (void**) &m_spViewObject);\r
+                       if (SUCCEEDED(hr))\r
+                               m_dwViewObjectType = 1;\r
+               }\r
+\r
+               CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());\r
+               m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);\r
+               if (m_spViewObject) \r
+               {\r
+                       m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);\r
+               }\r
+\r
+               m_spOleObject->SetHostNames(OLESTR("AXWIN"), NULL);\r
+\r
+               if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0) \r
+               {\r
+                       GetClientRect(&m_rcPos);\r
+\r
+                       m_pxSize.cx =  m_rcPos.right - m_rcPos.left;\r
+                       m_pxSize.cy =  m_rcPos.bottom - m_rcPos.top;\r
+                       AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\r
+                       m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+                       m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\r
+                       AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\r
+                       m_rcPos.right = m_rcPos.left + m_pxSize.cx ;\r
+                       m_rcPos.bottom = m_rcPos.top + m_pxSize.cy ;\r
+\r
+                       CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
+                       hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos);\r
+                       RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);\r
+               }\r
+       }\r
+\r
+       CComPtr<IObjectWithSite> spSite;\r
+       pUnKnown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\r
+       if (spSite != NULL) \r
+       {\r
+               spSite->SetSite(GetControllingUnknown());\r
+       }\r
+\r
+       return hr;\r
+}\r
diff --git a/modules/silverlight/interop/XcpControlHost.h b/modules/silverlight/interop/XcpControlHost.h
new file mode 100644 (file)
index 0000000..1098b95
--- /dev/null
@@ -0,0 +1,79 @@
+// XcpControlHost.h : Declaration of the XcpControlHost\r
+\r
+#pragma once\r
+\r
+#include <atlbase.h>\r
+#include <atlcom.h>\r
+#include <atlctl.h>\r
+\r
+#include "xcpctrl_h.h"\r
+\r
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)\r
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."\r
+#endif\r
+\r
+\r
+class XcpControlHost \r
+       : public ATL::CAxHostWindow\r
+       , public IXcpControlHost2\r
+{\r
+       HWND hControlWindow;\r
+       IUnknown* m_pUnKnown;\r
+       IXcpControl2* m_pControl;\r
+public: \r
+       XcpControlHost();\r
+       ~XcpControlHost();\r
+\r
+       typedef enum\r
+       {\r
+               XcpHostOption_FreezeOnInitialFrame       = 0x001,\r
+               XcpHostOption_DisableFullScreen          = 0x002,\r
+               XcpHostOption_DisableManagedExecution    = 0x008,\r
+               XcpHostOption_EnableCrossDomainDownloads = 0x010,\r
+               XcpHostOption_UseCustomAppDomain         = 0x020,\r
+               XcpHostOption_DisableNetworking          = 0x040,        \r
+               XcpHostOption_DisableScriptCallouts      = 0x080,\r
+               XcpHostOption_EnableHtmlDomAccess        = 0x100,\r
+               XcpHostOption_EnableScriptableObjectAccess = 0x200,\r
+       } XcpHostOptions;\r
+\r
+       \r
+   // IXcpControlHost implementation declarations\r
+       STDMETHOD(GetHostOptions)(DWORD* pdwOptions);\r
+       STDMETHOD(NotifyLoaded)();\r
+       STDMETHOD(NotifyError)(BSTR bstrError, BSTR bstrSource, long nLine, long nColumn);\r
+       STDMETHOD(InvokeHandler)(BSTR bstrName, VARIANT varParam1, VARIANT varParam2, VARIANT* pvarResult);\r
+       STDMETHOD(GetBaseUrl)(BSTR* pbstrUrl);\r
+       STDMETHOD(GetNamedSource)(BSTR bstrSourceID, BSTR* pbstrSource);\r
+       STDMETHOD(DownloadUrl)(BSTR bstrUrl, IXcpControlDownloadCallback* pCallback, IStream** ppStream);\r
+       STDMETHOD(GetCustomAppDomain)(IUnknown** ppAppDomain);\r
+       STDMETHOD(GetControlVersion)(UINT *puMajorVersion, UINT *puMinorVersion);\r
+       \r
+       // Infrastructure for control creation.\r
+       HRESULT CreateXcpControl(HWND hwnd);\r
+       HRESULT DestroyXcpControl();\r
+\r
+       DECLARE_NOT_AGGREGATABLE(XcpControlHost);\r
+\r
+       BEGIN_COM_MAP(XcpControlHost)\r
+               COM_INTERFACE_ENTRY(IXcpControlHost2)\r
+               COM_INTERFACE_ENTRY_CHAIN(CAxHostWindow)\r
+       END_COM_MAP()\r
+       \r
+       BEGIN_MSG_MAP(XcpControlHost)\r
+          CHAIN_MSG_MAP(CAxHostWindow)\r
+       END_MSG_MAP()\r
+\r
+       //IServiceProvider Implementation\r
+       STDMETHOD(QueryService)(REFGUID rsid, REFIID riid, void** ppvObj);\r
+\r
+       // ATL Overrides\r
+       STDMETHOD(AttachControl)(IUnknown* pUnkControl, HWND hWnd);\r
+       HRESULT ActivateXcpControl(IUnknown* pUnkControl);\r
+       \r
+       IXcpControl2* GetXcpControlPtr()\r
+       {\r
+               return m_pControl;\r
+       }\r
+};\r
+\r
diff --git a/modules/silverlight/interop/XcpPropertyBag.cpp b/modules/silverlight/interop/XcpPropertyBag.cpp
new file mode 100644 (file)
index 0000000..3a9a689
--- /dev/null
@@ -0,0 +1,76 @@
+#include "../StdAfx.h"\r
+\r
+#include "XcpPropertyBag.h"\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning (disable : 4100)\r
+#endif\r
+\r
+XcpPropertyBag::XcpPropertyBag(){m_RefCount=0;}\r
+XcpPropertyBag::~XcpPropertyBag(){}\r
+\r
+HRESULT STDMETHODCALLTYPE XcpPropertyBag::QueryInterface(REFIID iid, void** ppvObject)\r
+{\r
+       return S_OK;\r
+}\r
+\r
+ULONG STDMETHODCALLTYPE XcpPropertyBag::AddRef(void)\r
+{\r
+       return InterlockedIncrement((LONG*)&m_RefCount);\r
+}\r
+\r
+ULONG STDMETHODCALLTYPE XcpPropertyBag::Release(void)\r
+{\r
+       int             newRefValue;\r
+       \r
+       newRefValue = InterlockedDecrement((LONG*)&m_RefCount);\r
+       if (newRefValue == 0)\r
+       {\r
+               delete this;\r
+               return 0;\r
+       }\r
+       \r
+       return newRefValue;\r
+}\r
+\r
+STDMETHODIMP XcpPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)\r
+{\r
+       HRESULT hr = E_INVALIDARG;\r
+       BSTR bstrValue = NULL;\r
+         \r
+       if (_wcsicmp(pszPropName, L"Source") == 0) \r
+       {\r
+               bstrValue = SysAllocString(L"SilverlightBalls.xap");\r
+       }    \r
+       else if (_wcsicmp(pszPropName, L"Background") == 0) \r
+       {\r
+               bstrValue = SysAllocString(L"Transparent");\r
+       }\r
+       else if (_wcsicmp(pszPropName, L"EnableGPUAcceleration") == 0) \r
+       {\r
+               V_VT(pVar) = VT_BOOL;\r
+               V_BOOL(pVar) = VARIANT_TRUE;\r
+               hr = S_OK;\r
+       }\r
+\r
+       else if (_wcsicmp(pszPropName, L"Windowless") == 0) \r
+       {\r
+               V_VT(pVar) = VT_BOOL;\r
+               V_BOOL(pVar) = VARIANT_FALSE;\r
+               hr = S_OK;\r
+       }\r
+\r
+       if (bstrValue != NULL) \r
+       {\r
+               V_VT(pVar) = VT_BSTR;\r
+               V_BSTR(pVar) = bstrValue;\r
+               hr = S_OK;\r
+       }\r
+       return hr;\r
+}\r
+\r
+       \r
+STDMETHODIMP XcpPropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pVar)\r
+{\r
+       return S_OK;\r
+}
\ No newline at end of file
diff --git a/modules/silverlight/interop/XcpPropertyBag.h b/modules/silverlight/interop/XcpPropertyBag.h
new file mode 100644 (file)
index 0000000..6026029
--- /dev/null
@@ -0,0 +1,23 @@
+#pragma once\r
+\r
+#include "Ocidl.h"\r
+#include "xcpctrl_h.h"\r
+\r
+#include "atlstr.h"\r
+\r
+using namespace ATL;\r
+\r
+class XcpPropertyBag : public IPropertyBag\r
+{\r
+       int m_RefCount;\r
+public:\r
+       XcpPropertyBag();\r
+       ~XcpPropertyBag();\r
+\r
+       HRESULT _stdcall QueryInterface(REFIID iid, void** ppvObject);\r
+       ULONG _stdcall AddRef();        \r
+       ULONG _stdcall Release();\r
+\r
+       STDMETHOD (Read)(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog);   \r
+       STDMETHOD (Write)(LPCOLESTR pszPropName, VARIANT *pVar);\r
+};
\ No newline at end of file
diff --git a/modules/silverlight/interop/xcpctrl.h b/modules/silverlight/interop/xcpctrl.h
new file mode 100644 (file)
index 0000000..8b12518
--- /dev/null
@@ -0,0 +1,1366 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */\r
+\r
+\r
+ /* File created by MIDL compiler version 7.00.0555 */\r
+/* at Sat Jan 22 19:48:54 2011\r
+ */\r
+/* Compiler settings for xcpctrl.idl:\r
+    Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+/* @@MIDL_FILE_HEADING(  ) */\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+\r
+\r
+/* verify that the <rpcndr.h> version is high enough to compile this file*/\r
+#ifndef __REQUIRED_RPCNDR_H_VERSION__\r
+#define __REQUIRED_RPCNDR_H_VERSION__ 475\r
+#endif\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+\r
+#ifndef __RPCNDR_H_VERSION__\r
+#error this stub requires an updated version of <rpcndr.h>\r
+#endif // __RPCNDR_H_VERSION__\r
+\r
+#ifndef COM_NO_WINDOWS_H\r
+#include "windows.h"\r
+#include "ole2.h"\r
+#endif /*COM_NO_WINDOWS_H*/\r
+\r
+#ifndef __xcpctrl_h__\r
+#define __xcpctrl_h__\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+#pragma once\r
+#endif\r
+\r
+/* Forward Declarations */ \r
+\r
+#ifndef __IXcpObject_FWD_DEFINED__\r
+#define __IXcpObject_FWD_DEFINED__\r
+typedef interface IXcpObject IXcpObject;\r
+#endif         /* __IXcpObject_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl_FWD_DEFINED__\r
+#define __IXcpControl_FWD_DEFINED__\r
+typedef interface IXcpControl IXcpControl;\r
+#endif         /* __IXcpControl_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl2_FWD_DEFINED__\r
+#define __IXcpControl2_FWD_DEFINED__\r
+typedef interface IXcpControl2 IXcpControl2;\r
+#endif         /* __IXcpControl2_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlDownloadCallback_FWD_DEFINED__\r
+#define __IXcpControlDownloadCallback_FWD_DEFINED__\r
+typedef interface IXcpControlDownloadCallback IXcpControlDownloadCallback;\r
+#endif         /* __IXcpControlDownloadCallback_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost_FWD_DEFINED__\r
+#define __IXcpControlHost_FWD_DEFINED__\r
+typedef interface IXcpControlHost IXcpControlHost;\r
+#endif         /* __IXcpControlHost_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost2_FWD_DEFINED__\r
+#define __IXcpControlHost2_FWD_DEFINED__\r
+typedef interface IXcpControlHost2 IXcpControlHost2;\r
+#endif         /* __IXcpControlHost2_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost3_FWD_DEFINED__\r
+#define __IXcpControlHost3_FWD_DEFINED__\r
+typedef interface IXcpControlHost3 IXcpControlHost3;\r
+#endif         /* __IXcpControlHost3_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __XcpControl_FWD_DEFINED__\r
+#define __XcpControl_FWD_DEFINED__\r
+\r
+#ifdef __cplusplus\r
+typedef class XcpControl XcpControl;\r
+#else\r
+typedef struct XcpControl XcpControl;\r
+#endif /* __cplusplus */\r
+\r
+#endif         /* __XcpControl_FWD_DEFINED__ */\r
+\r
+\r
+/* header files for imported files */\r
+#include "oaidl.h"\r
+#include "ocidl.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif \r
+\r
+\r
+#ifndef __IXcpObject_INTERFACE_DEFINED__\r
+#define __IXcpObject_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpObject */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpObject;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("EE38D0F1-5AE3-408c-A6BF-8410E645F376")\r
+    IXcpObject : public IDispatch\r
+    {\r
+    public:\r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpObjectVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpObject * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpObject * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpObject * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpObject * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpObject * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpObject * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpObject * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        END_INTERFACE\r
+    } IXcpObjectVtbl;\r
+\r
+    interface IXcpObject\r
+    {\r
+        CONST_VTBL struct IXcpObjectVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpObject_QueryInterface(This,riid,ppvObject) \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpObject_AddRef(This)        \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpObject_Release(This)       \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpObject_GetTypeInfoCount(This,pctinfo)      \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo)       \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)     \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)       \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpObject_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl_INTERFACE_DEFINED__\r
+#define __IXcpControl_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControl */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControl;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1FB839CC-116C-4C9B-AE8E-3DBB6496E326")\r
+    IXcpControl : public IDispatch\r
+    {\r
+    public:\r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Source( \r
+            /* [retval][out] */ BSTR *pstr) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_Source( \r
+            /* [in] */ BSTR str) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_IsLoaded( \r
+            /* [retval][out] */ VARIANT_BOOL *pb) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Content( \r
+            /* [retval][out] */ IDispatch **ppContent) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Settings( \r
+            /* [retval][out] */ IDispatch **ppSettings) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnLoad( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnLoad( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnError( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnError( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE CreateObject( \r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE IsVersionSupported( \r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_InitParams( \r
+            /* [retval][out] */ BSTR *initparams) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_InitParams( \r
+            /* [in] */ BSTR initparams) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControl * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControl * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControl * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpControl * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpControl * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpControl * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpControl * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Source )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsLoaded )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ IDispatch **ppContent);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ IDispatch **ppSettings);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnLoad )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnLoad )( \r
+            IXcpControl * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnError )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnError )( \r
+            IXcpControl * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *CreateObject )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *IsVersionSupported )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InitParams )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ BSTR *initparams);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InitParams )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR initparams);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlVtbl;\r
+\r
+    interface IXcpControl\r
+    {\r
+        CONST_VTBL struct IXcpControlVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControl_QueryInterface(This,riid,ppvObject)        \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControl_AddRef(This)       \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControl_Release(This)      \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControl_GetTypeInfoCount(This,pctinfo)     \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo)      \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)    \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)      \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#define IXcpControl_get_Source(This,pstr)      \\r
+    ( (This)->lpVtbl -> get_Source(This,pstr) ) \r
+\r
+#define IXcpControl_put_Source(This,str)       \\r
+    ( (This)->lpVtbl -> put_Source(This,str) ) \r
+\r
+#define IXcpControl_get_IsLoaded(This,pb)      \\r
+    ( (This)->lpVtbl -> get_IsLoaded(This,pb) ) \r
+\r
+#define IXcpControl_get_Content(This,ppContent)        \\r
+    ( (This)->lpVtbl -> get_Content(This,ppContent) ) \r
+\r
+#define IXcpControl_get_Settings(This,ppSettings)      \\r
+    ( (This)->lpVtbl -> get_Settings(This,ppSettings) ) \r
+\r
+#define IXcpControl_get_OnLoad(This,pVAR)      \\r
+    ( (This)->lpVtbl -> get_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl_put_OnLoad(This,pVAR)      \\r
+    ( (This)->lpVtbl -> put_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl_get_OnError(This,pVAR)     \\r
+    ( (This)->lpVtbl -> get_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl_put_OnError(This,pVAR)     \\r
+    ( (This)->lpVtbl -> put_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl_CreateObject(This,id,ppDisp)       \\r
+    ( (This)->lpVtbl -> CreateObject(This,id,ppDisp) ) \r
+\r
+#define IXcpControl_IsVersionSupported(This,v,pb)      \\r
+    ( (This)->lpVtbl -> IsVersionSupported(This,v,pb) ) \r
+\r
+#define IXcpControl_get_InitParams(This,initparams)    \\r
+    ( (This)->lpVtbl -> get_InitParams(This,initparams) ) \r
+\r
+#define IXcpControl_put_InitParams(This,initparams)    \\r
+    ( (This)->lpVtbl -> put_InitParams(This,initparams) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControl_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl2_INTERFACE_DEFINED__\r
+#define __IXcpControl2_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControl2 */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControl2;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1c3294f9-891f-49b1-bbae-492a68ba10cc")\r
+    IXcpControl2 : public IXcpControl\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE LoadRuntime( void) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_SplashScreenSource( \r
+            /* [retval][out] */ BSTR *pstr) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_SplashScreenSource( \r
+            /* [in] */ BSTR str) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnSourceDownloadComplete( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnSourceDownloadComplete( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnSourceDownloadProgressChanged( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnSourceDownloadProgressChanged( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControl2Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControl2 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControl2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpControl2 * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Source )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsLoaded )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ IDispatch **ppContent);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ IDispatch **ppSettings);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnLoad )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnLoad )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnError )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnError )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *CreateObject )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *IsVersionSupported )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InitParams )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *initparams);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InitParams )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR initparams);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *LoadRuntime )( \r
+            IXcpControl2 * This);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SplashScreenSource )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SplashScreenSource )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnSourceDownloadComplete )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnSourceDownloadComplete )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnSourceDownloadProgressChanged )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnSourceDownloadProgressChanged )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControl2Vtbl;\r
+\r
+    interface IXcpControl2\r
+    {\r
+        CONST_VTBL struct IXcpControl2Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControl2_QueryInterface(This,riid,ppvObject)       \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControl2_AddRef(This)      \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControl2_Release(This)     \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControl2_GetTypeInfoCount(This,pctinfo)    \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpControl2_GetTypeInfo(This,iTInfo,lcid,ppTInfo)     \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpControl2_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)   \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpControl2_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)     \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#define IXcpControl2_get_Source(This,pstr)     \\r
+    ( (This)->lpVtbl -> get_Source(This,pstr) ) \r
+\r
+#define IXcpControl2_put_Source(This,str)      \\r
+    ( (This)->lpVtbl -> put_Source(This,str) ) \r
+\r
+#define IXcpControl2_get_IsLoaded(This,pb)     \\r
+    ( (This)->lpVtbl -> get_IsLoaded(This,pb) ) \r
+\r
+#define IXcpControl2_get_Content(This,ppContent)       \\r
+    ( (This)->lpVtbl -> get_Content(This,ppContent) ) \r
+\r
+#define IXcpControl2_get_Settings(This,ppSettings)     \\r
+    ( (This)->lpVtbl -> get_Settings(This,ppSettings) ) \r
+\r
+#define IXcpControl2_get_OnLoad(This,pVAR)     \\r
+    ( (This)->lpVtbl -> get_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnLoad(This,pVAR)     \\r
+    ( (This)->lpVtbl -> put_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl2_get_OnError(This,pVAR)    \\r
+    ( (This)->lpVtbl -> get_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnError(This,pVAR)    \\r
+    ( (This)->lpVtbl -> put_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl2_CreateObject(This,id,ppDisp)      \\r
+    ( (This)->lpVtbl -> CreateObject(This,id,ppDisp) ) \r
+\r
+#define IXcpControl2_IsVersionSupported(This,v,pb)     \\r
+    ( (This)->lpVtbl -> IsVersionSupported(This,v,pb) ) \r
+\r
+#define IXcpControl2_get_InitParams(This,initparams)   \\r
+    ( (This)->lpVtbl -> get_InitParams(This,initparams) ) \r
+\r
+#define IXcpControl2_put_InitParams(This,initparams)   \\r
+    ( (This)->lpVtbl -> put_InitParams(This,initparams) ) \r
+\r
+\r
+#define IXcpControl2_LoadRuntime(This) \\r
+    ( (This)->lpVtbl -> LoadRuntime(This) ) \r
+\r
+#define IXcpControl2_get_SplashScreenSource(This,pstr) \\r
+    ( (This)->lpVtbl -> get_SplashScreenSource(This,pstr) ) \r
+\r
+#define IXcpControl2_put_SplashScreenSource(This,str)  \\r
+    ( (This)->lpVtbl -> put_SplashScreenSource(This,str) ) \r
+\r
+#define IXcpControl2_get_OnSourceDownloadComplete(This,pVAR)   \\r
+    ( (This)->lpVtbl -> get_OnSourceDownloadComplete(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnSourceDownloadComplete(This,pVAR)   \\r
+    ( (This)->lpVtbl -> put_OnSourceDownloadComplete(This,pVAR) ) \r
+\r
+#define IXcpControl2_get_OnSourceDownloadProgressChanged(This,pVAR)    \\r
+    ( (This)->lpVtbl -> get_OnSourceDownloadProgressChanged(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnSourceDownloadProgressChanged(This,pVAR)    \\r
+    ( (This)->lpVtbl -> put_OnSourceDownloadProgressChanged(This,pVAR) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControl2_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlDownloadCallback_INTERFACE_DEFINED__\r
+#define __IXcpControlDownloadCallback_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlDownloadCallback */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlDownloadCallback;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("2E340632-5D5A-427b-AC31-303F6E32B9E8")\r
+    IXcpControlDownloadCallback : public IUnknown\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE OnUrlDownloaded( \r
+            HRESULT hr,\r
+            IStream *pStream) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlDownloadCallbackVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlDownloadCallback * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlDownloadCallback * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlDownloadCallback * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *OnUrlDownloaded )( \r
+            IXcpControlDownloadCallback * This,\r
+            HRESULT hr,\r
+            IStream *pStream);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlDownloadCallbackVtbl;\r
+\r
+    interface IXcpControlDownloadCallback\r
+    {\r
+        CONST_VTBL struct IXcpControlDownloadCallbackVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlDownloadCallback_QueryInterface(This,riid,ppvObject)        \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlDownloadCallback_AddRef(This)       \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlDownloadCallback_Release(This)      \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlDownloadCallback_OnUrlDownloaded(This,hr,pStream)   \\r
+    ( (This)->lpVtbl -> OnUrlDownloaded(This,hr,pStream) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlDownloadCallback_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost_INTERFACE_DEFINED__\r
+#define __IXcpControlHost_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+typedef /* [public] */ \r
+enum __MIDL_IXcpControlHost_0001\r
+    {  XcpHostOption_FreezeOnInitialFrame      = 0x1,\r
+       XcpHostOption_DisableFullScreen = 0x2,\r
+       XcpHostOption_DisableManagedExecution   = 0x8,\r
+       XcpHostOption_EnableCrossDomainDownloads        = 0x10,\r
+       XcpHostOption_UseCustomAppDomain        = 0x20,\r
+       XcpHostOption_DisableNetworking = 0x40,\r
+       XcpHostOption_DisableScriptCallouts     = 0x80,\r
+       XcpHostOption_EnableHtmlDomAccess       = 0x100,\r
+       XcpHostOption_EnableScriptableObjectAccess      = 0x200,\r
+       XcpHostOption_EnableAssemblySharing     = 0x800,\r
+       XcpHostOption_HookGetComAutomationObject        = 0x1000,\r
+       XcpHostOption_EnableElevatedPermissions = 0x2000,\r
+       XcpHostOption_EnableWindowlessAccessibility     = 0x4000\r
+    }  XcpHostOptions;\r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1B36028E-B491-4bb2-8584-8A9E0A677D6E")\r
+    IXcpControlHost : public IUnknown\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetHostOptions( \r
+            /* [retval][out] */ DWORD *pdwOptions) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE NotifyLoaded( void) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE NotifyError( \r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE InvokeHandler( \r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetBaseUrl( \r
+            /* [retval][out] */ BSTR *pbstrUrl) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetNamedSource( \r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE DownloadUrl( \r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHostVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHostVtbl;\r
+\r
+    interface IXcpControlHost\r
+    {\r
+        CONST_VTBL struct IXcpControlHostVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost_QueryInterface(This,riid,ppvObject)    \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost_AddRef(This)   \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost_Release(This)  \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost_GetHostOptions(This,pdwOptions)        \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost_NotifyLoaded(This)     \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost_NotifyError(This,bstrError,bstrSource,nLine,nColumn)   \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)        \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost_GetBaseUrl(This,pbstrUrl)      \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost_GetNamedSource(This,bstrSourceName,pbstrSource)        \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost_DownloadUrl(This,bstrUrl,pCallback,ppStream)   \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost2_INTERFACE_DEFINED__\r
+#define __IXcpControlHost2_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost2 */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost2;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("fb3ed7c4-5797-4b44-8695-0c512ea27d8f")\r
+    IXcpControlHost2 : public IXcpControlHost\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetCustomAppDomain( \r
+            /* [retval][out] */ IUnknown **ppAppDomain) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetControlVersion( \r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHost2Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetCustomAppDomain )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ IUnknown **ppAppDomain);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetControlVersion )( \r
+            IXcpControlHost2 * This,\r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHost2Vtbl;\r
+\r
+    interface IXcpControlHost2\r
+    {\r
+        CONST_VTBL struct IXcpControlHost2Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost2_QueryInterface(This,riid,ppvObject)   \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost2_AddRef(This)  \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost2_Release(This) \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost2_GetHostOptions(This,pdwOptions)       \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost2_NotifyLoaded(This)    \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost2_NotifyError(This,bstrError,bstrSource,nLine,nColumn)  \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost2_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)       \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost2_GetBaseUrl(This,pbstrUrl)     \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost2_GetNamedSource(This,bstrSourceName,pbstrSource)       \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost2_DownloadUrl(This,bstrUrl,pCallback,ppStream)  \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+\r
+#define IXcpControlHost2_GetCustomAppDomain(This,ppAppDomain)  \\r
+    ( (This)->lpVtbl -> GetCustomAppDomain(This,ppAppDomain) ) \r
+\r
+#define IXcpControlHost2_GetControlVersion(This,puMajorVersion,puMinorVersion) \\r
+    ( (This)->lpVtbl -> GetControlVersion(This,puMajorVersion,puMinorVersion) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost2_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost3_INTERFACE_DEFINED__\r
+#define __IXcpControlHost3_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost3 */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+typedef /* [public] */ \r
+enum __MIDL_IXcpControlHost3_0001\r
+    {  XcpHost_GetComAutomationObjectFlag_Get  = 0x1,\r
+       XcpHost_GetComAutomationObjectFlag_Create       = 0x2\r
+    }  XcpHost_GetComAutomationObjectFlags;\r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost3;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("9fb2ce5f-06ff-4058-befa-ddfab596b3d5")\r
+    IXcpControlHost3 : public IXcpControlHost2\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetDefaultThemeXaml( \r
+            /* [in] */ BSTR assemblyName,\r
+            /* [retval][out] */ LPBSTR pbstrXaml) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetDefaultPortableUserInterfaceFontInfo( \r
+            /* [retval][out] */ LPBSTR pbstrCompositeFont) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetComAutomationObject( \r
+            /* [in] */ BSTR bstrProgId,\r
+            /* [in] */ DWORD dwFlags,\r
+            /* [retval][out] */ IDispatch **ppDisp) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHost3Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetCustomAppDomain )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ IUnknown **ppAppDomain);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetControlVersion )( \r
+            IXcpControlHost3 * This,\r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetDefaultThemeXaml )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR assemblyName,\r
+            /* [retval][out] */ LPBSTR pbstrXaml);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetDefaultPortableUserInterfaceFontInfo )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ LPBSTR pbstrCompositeFont);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetComAutomationObject )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrProgId,\r
+            /* [in] */ DWORD dwFlags,\r
+            /* [retval][out] */ IDispatch **ppDisp);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHost3Vtbl;\r
+\r
+    interface IXcpControlHost3\r
+    {\r
+        CONST_VTBL struct IXcpControlHost3Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost3_QueryInterface(This,riid,ppvObject)   \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost3_AddRef(This)  \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost3_Release(This) \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost3_GetHostOptions(This,pdwOptions)       \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost3_NotifyLoaded(This)    \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost3_NotifyError(This,bstrError,bstrSource,nLine,nColumn)  \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost3_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)       \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost3_GetBaseUrl(This,pbstrUrl)     \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost3_GetNamedSource(This,bstrSourceName,pbstrSource)       \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost3_DownloadUrl(This,bstrUrl,pCallback,ppStream)  \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+\r
+#define IXcpControlHost3_GetCustomAppDomain(This,ppAppDomain)  \\r
+    ( (This)->lpVtbl -> GetCustomAppDomain(This,ppAppDomain) ) \r
+\r
+#define IXcpControlHost3_GetControlVersion(This,puMajorVersion,puMinorVersion) \\r
+    ( (This)->lpVtbl -> GetControlVersion(This,puMajorVersion,puMinorVersion) ) \r
+\r
+\r
+#define IXcpControlHost3_GetDefaultThemeXaml(This,assemblyName,pbstrXaml)      \\r
+    ( (This)->lpVtbl -> GetDefaultThemeXaml(This,assemblyName,pbstrXaml) ) \r
+\r
+#define IXcpControlHost3_GetDefaultPortableUserInterfaceFontInfo(This,pbstrCompositeFont)      \\r
+    ( (This)->lpVtbl -> GetDefaultPortableUserInterfaceFontInfo(This,pbstrCompositeFont) ) \r
+\r
+#define IXcpControlHost3_GetComAutomationObject(This,bstrProgId,dwFlags,ppDisp)        \\r
+    ( (This)->lpVtbl -> GetComAutomationObject(This,bstrProgId,dwFlags,ppDisp) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost3_INTERFACE_DEFINED__ */\r
+\r
+\r
+\r
+#ifndef __XcpControlLib_LIBRARY_DEFINED__\r
+#define __XcpControlLib_LIBRARY_DEFINED__\r
+\r
+/* library XcpControlLib */\r
+/* [control][helpstring][version][uuid] */ \r
+\r
+\r
+EXTERN_C const IID LIBID_XcpControlLib;\r
+\r
+EXTERN_C const CLSID CLSID_XcpControl;\r
+\r
+#ifdef __cplusplus\r
+\r
+class DECLSPEC_UUID("DFEAF541-F3E1-4c24-ACAC-99C30715084A")\r
+XcpControl;\r
+#endif\r
+#endif /* __XcpControlLib_LIBRARY_DEFINED__ */\r
+\r
+/* Additional Prototypes for ALL interfaces */\r
+\r
+unsigned long             __RPC_USER  BSTR_UserSize(     unsigned long *, unsigned long            , BSTR * ); \r
+unsigned char * __RPC_USER  BSTR_UserMarshal(  unsigned long *, unsigned char *, BSTR * ); \r
+unsigned char * __RPC_USER  BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); \r
+void                      __RPC_USER  BSTR_UserFree(     unsigned long *, BSTR * ); \r
+\r
+unsigned long             __RPC_USER  VARIANT_UserSize(     unsigned long *, unsigned long            , VARIANT * ); \r
+unsigned char * __RPC_USER  VARIANT_UserMarshal(  unsigned long *, unsigned char *, VARIANT * ); \r
+unsigned char * __RPC_USER  VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); \r
+void                      __RPC_USER  VARIANT_UserFree(     unsigned long *, VARIANT * ); \r
+\r
+/* end of Additional Prototypes */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
diff --git a/modules/silverlight/interop/xcpctrl.idl b/modules/silverlight/interop/xcpctrl.idl
new file mode 100644 (file)
index 0000000..c3d4704
--- /dev/null
@@ -0,0 +1,226 @@
+//------------------------------------------------------------------------\r
+//\r
+//  Copyright (c) 2005  Microsoft Corporation\r
+//\r
+//  Abstract:\r
+//\r
+//      IDL file for activex control\r
+//\r
+//\r
+//------------------------------------------------------------------------\r
+//\r
+\r
+#include "olectl.h"\r
+import "oaidl.idl";\r
+import "ocidl.idl";\r
+\r
+[\r
+    object,\r
+    uuid(EE38D0F1-5AE3-408c-A6BF-8410E645F376),\r
+    dual,\r
+    nonextensible,\r
+    helpstring("IXcpObject Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpObject : IDispatch\r
+{\r
+};\r
+\r
+\r
+[\r
+    object,\r
+    uuid(1FB839CC-116C-4C9B-AE8E-3DBB6496E326),\r
+    dual,\r
+    nonextensible,\r
+    helpstring("IXcpControl Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControl : IDispatch\r
+{\r
+    [propget, bindable, requestedit]\r
+    HRESULT Source([out, retval]  BSTR *pstr);\r
+    [propput, bindable, requestedit]\r
+    HRESULT Source([in] BSTR str);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT IsLoaded([out, retval]  VARIANT_BOOL *pb);\r
+\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT Content([out, retval]  IDispatch **ppContent);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT Settings([out, retval]  IDispatch **ppSettings);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT OnLoad([out, retval] VARIANT* pVAR);\r
+    [propput, bindable, requestedit]\r
+    HRESULT OnLoad([in] VARIANT* pVAR);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT OnError([out, retval] VARIANT* pVAR);\r
+    [propput, bindable, requestedit]\r
+    HRESULT OnError([in] VARIANT* pVAR);\r
+\r
+    HRESULT CreateObject([in] BSTR id, [out, retval] IXcpObject** ppDisp);\r
+\r
+    HRESULT IsVersionSupported([in] BSTR v, [out, retval] VARIANT_BOOL *pb);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT InitParams([out, retval] BSTR * initparams);\r
+    [propput, bindable, requestedit]\r
+    HRESULT InitParams([in] BSTR initparams);\r
+};\r
+\r
+[\r
+    object,\r
+    uuid(1c3294f9-891f-49b1-bbae-492a68ba10cc),\r
+    dual,\r
+    nonextensible,\r
+    helpstring("IXcpControl2 Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControl2 : IXcpControl\r
+{\r
+    HRESULT LoadRuntime();\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT SplashScreenSource([out, retval]  BSTR *pstr);\r
+    [propput, bindable, requestedit]\r
+    HRESULT SplashScreenSource([in] BSTR str);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT OnSourceDownloadComplete([out, retval] VARIANT* pVAR);\r
+    [propput, bindable, requestedit]\r
+    HRESULT OnSourceDownloadComplete([in] VARIANT* pVAR);\r
+\r
+    [propget, bindable, requestedit]\r
+    HRESULT OnSourceDownloadProgressChanged([out, retval] VARIANT* pVAR);\r
+    [propput, bindable, requestedit]\r
+    HRESULT OnSourceDownloadProgressChanged([in] VARIANT* pVAR);\r
+};\r
+\r
+[\r
+    object,\r
+    uuid(2E340632-5D5A-427b-AC31-303F6E32B9E8),\r
+    nonextensible,\r
+    helpstring("IXcpControlDownloadCallback Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControlDownloadCallback : IUnknown\r
+{\r
+    HRESULT OnUrlDownloaded(HRESULT hr, IStream* pStream);\r
+};\r
+\r
+[\r
+    object,\r
+    uuid(1B36028E-B491-4bb2-8584-8A9E0A677D6E),\r
+    nonextensible,\r
+    helpstring("IXcpControlHost Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControlHost : IUnknown\r
+{\r
+    typedef enum\r
+    {\r
+        XcpHostOption_FreezeOnInitialFrame         = 0x001,\r
+        XcpHostOption_DisableFullScreen            = 0x002,\r
+        XcpHostOption_DisableManagedExecution      = 0x008,\r
+        XcpHostOption_EnableCrossDomainDownloads   = 0x010,\r
+        XcpHostOption_UseCustomAppDomain           = 0x020,\r
+        XcpHostOption_DisableNetworking            = 0x040,        \r
+        XcpHostOption_DisableScriptCallouts        = 0x080,\r
+        XcpHostOption_EnableHtmlDomAccess          = 0x100,\r
+        XcpHostOption_EnableScriptableObjectAccess = 0x200,\r
+        // Skipping a number so as not to conflict with mobile.\r
+        XcpHostOption_EnableAssemblySharing        = 0x800,\r
+        XcpHostOption_HookGetComAutomationObject   = 0x1000,\r
+        XcpHostOption_EnableElevatedPermissions    = 0x2000,\r
+        XcpHostOption_EnableWindowlessAccessibility = 0x4000,\r
+    } XcpHostOptions;\r
+\r
+    HRESULT GetHostOptions([out, retval] DWORD* pdwOptions);\r
+\r
+    HRESULT NotifyLoaded();\r
+\r
+    HRESULT NotifyError([in] BSTR bstrError, [in] BSTR bstrSource, [in] long nLine, [in] long nColumn);\r
+\r
+    HRESULT InvokeHandler([in] BSTR bstrName, [in] VARIANT varArg1, [in] VARIANT varArg2, [out, retval] VARIANT* pvarResult);\r
+\r
+    HRESULT GetBaseUrl([out, retval] BSTR* pbstrUrl);\r
+\r
+    HRESULT GetNamedSource([in] BSTR bstrSourceName, [out, retval] BSTR* pbstrSource);\r
+\r
+    //\r
+    // Called by Silverlight to allow a host to provide content for a specified URI. This is useful in cases\r
+    // where a resource would normally be loaded out of a XAP at runtime. At design time, no XAP exists, and\r
+    // the host can provide content for that resource.\r
+    //\r
+    // This method can work synchronously or asynchronously. If the pCallback parameter is NULL, the host must\r
+    // do the work synchronously and return the result in ppStream. If the pCallback parameter is non-NULL, the host\r
+    // may do the work synchronously or asynchronously, invoking callback methods as defined by the \r
+    // IXcpControlDownloadCallback interface. If the host chooses to work asyncronously, the ppStream parameter is\r
+    // ignored.\r
+    //\r
+    // The host should return S_FALSE if it cannot provide a resource for the requested URI, and S_OK on a\r
+    // successful request.\r
+    //\r
+    HRESULT DownloadUrl([in] BSTR bstrUrl, [in] IXcpControlDownloadCallback* pCallback, [out, retval] IStream** ppStream);\r
+\r
+};\r
+\r
+[\r
+    object,\r
+    uuid(fb3ed7c4-5797-4b44-8695-0c512ea27d8f),\r
+    nonextensible,\r
+    helpstring("IXcpControlHost2 Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControlHost2 : IXcpControlHost\r
+{\r
+    HRESULT GetCustomAppDomain([out, retval] IUnknown** ppAppDomain);\r
+\r
+    HRESULT GetControlVersion([out] UINT *puMajorVersion, [out] UINT *puMinorVersion);\r
+};\r
+\r
+[\r
+    object,\r
+    uuid(9fb2ce5f-06ff-4058-befa-ddfab596b3d5),\r
+    nonextensible,\r
+    helpstring("IXcpControlHost3 Interface"),\r
+    pointer_default(unique)\r
+]\r
+interface IXcpControlHost3 : IXcpControlHost2\r
+{\r
+    HRESULT GetDefaultThemeXaml([in] BSTR assemblyName, [out, retval] LPBSTR pbstrXaml);\r
+    \r
+    HRESULT GetDefaultPortableUserInterfaceFontInfo([out, retval] LPBSTR pbstrCompositeFont);\r
+\r
+    typedef enum\r
+    {\r
+        XcpHost_GetComAutomationObjectFlag_Get    = 0x1,\r
+        XcpHost_GetComAutomationObjectFlag_Create = 0x2\r
+    } XcpHost_GetComAutomationObjectFlags;\r
+\r
+    HRESULT GetComAutomationObject([in] BSTR bstrProgId, [in] DWORD dwFlags, [out, retval] IDispatch** ppDisp);\r
+};\r
+\r
+[\r
+    uuid(283C8576-0726-4DBC-9609-3F855162009A),\r
+    version(4.0),\r
+    helpstring("AgControl 4.0 Type Library"),\r
+    control\r
+]\r
+library XcpControlLib\r
+{\r
+    importlib("stdole2.tlb");\r
+    [\r
+        uuid(DFEAF541-F3E1-4c24-ACAC-99C30715084A),\r
+        helpstring("AgControl Class")\r
+    ]\r
+    coclass XcpControl\r
+    {\r
+        [default] interface IXcpControl2;\r
+        interface IXcpControl;\r
+    };\r
+};\r
diff --git a/modules/silverlight/interop/xcpctrl_h.h b/modules/silverlight/interop/xcpctrl_h.h
new file mode 100644 (file)
index 0000000..79b6d5b
--- /dev/null
@@ -0,0 +1,1366 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */\r
+\r
+\r
+ /* File created by MIDL compiler version 7.00.0555 */\r
+/* at Sat Jan 22 19:55:15 2011\r
+ */\r
+/* Compiler settings for xcpctrl.idl:\r
+    Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+/* @@MIDL_FILE_HEADING(  ) */\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+\r
+\r
+/* verify that the <rpcndr.h> version is high enough to compile this file*/\r
+#ifndef __REQUIRED_RPCNDR_H_VERSION__\r
+#define __REQUIRED_RPCNDR_H_VERSION__ 475\r
+#endif\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+\r
+#ifndef __RPCNDR_H_VERSION__\r
+#error this stub requires an updated version of <rpcndr.h>\r
+#endif // __RPCNDR_H_VERSION__\r
+\r
+#ifndef COM_NO_WINDOWS_H\r
+#include "windows.h"\r
+#include "ole2.h"\r
+#endif /*COM_NO_WINDOWS_H*/\r
+\r
+#ifndef __xcpctrl_h_h__\r
+#define __xcpctrl_h_h__\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+#pragma once\r
+#endif\r
+\r
+/* Forward Declarations */ \r
+\r
+#ifndef __IXcpObject_FWD_DEFINED__\r
+#define __IXcpObject_FWD_DEFINED__\r
+typedef interface IXcpObject IXcpObject;\r
+#endif         /* __IXcpObject_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl_FWD_DEFINED__\r
+#define __IXcpControl_FWD_DEFINED__\r
+typedef interface IXcpControl IXcpControl;\r
+#endif         /* __IXcpControl_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl2_FWD_DEFINED__\r
+#define __IXcpControl2_FWD_DEFINED__\r
+typedef interface IXcpControl2 IXcpControl2;\r
+#endif         /* __IXcpControl2_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlDownloadCallback_FWD_DEFINED__\r
+#define __IXcpControlDownloadCallback_FWD_DEFINED__\r
+typedef interface IXcpControlDownloadCallback IXcpControlDownloadCallback;\r
+#endif         /* __IXcpControlDownloadCallback_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost_FWD_DEFINED__\r
+#define __IXcpControlHost_FWD_DEFINED__\r
+typedef interface IXcpControlHost IXcpControlHost;\r
+#endif         /* __IXcpControlHost_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost2_FWD_DEFINED__\r
+#define __IXcpControlHost2_FWD_DEFINED__\r
+typedef interface IXcpControlHost2 IXcpControlHost2;\r
+#endif         /* __IXcpControlHost2_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost3_FWD_DEFINED__\r
+#define __IXcpControlHost3_FWD_DEFINED__\r
+typedef interface IXcpControlHost3 IXcpControlHost3;\r
+#endif         /* __IXcpControlHost3_FWD_DEFINED__ */\r
+\r
+\r
+#ifndef __XcpControl_FWD_DEFINED__\r
+#define __XcpControl_FWD_DEFINED__\r
+\r
+#ifdef __cplusplus\r
+typedef class XcpControl XcpControl;\r
+#else\r
+typedef struct XcpControl XcpControl;\r
+#endif /* __cplusplus */\r
+\r
+#endif         /* __XcpControl_FWD_DEFINED__ */\r
+\r
+\r
+/* header files for imported files */\r
+#include "oaidl.h"\r
+#include "ocidl.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif \r
+\r
+\r
+#ifndef __IXcpObject_INTERFACE_DEFINED__\r
+#define __IXcpObject_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpObject */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpObject;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("EE38D0F1-5AE3-408c-A6BF-8410E645F376")\r
+    IXcpObject : public IDispatch\r
+    {\r
+    public:\r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpObjectVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpObject * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpObject * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpObject * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpObject * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpObject * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpObject * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpObject * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        END_INTERFACE\r
+    } IXcpObjectVtbl;\r
+\r
+    interface IXcpObject\r
+    {\r
+        CONST_VTBL struct IXcpObjectVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpObject_QueryInterface(This,riid,ppvObject) \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpObject_AddRef(This)        \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpObject_Release(This)       \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpObject_GetTypeInfoCount(This,pctinfo)      \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo)       \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)     \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)       \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpObject_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl_INTERFACE_DEFINED__\r
+#define __IXcpControl_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControl */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControl;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1FB839CC-116C-4C9B-AE8E-3DBB6496E326")\r
+    IXcpControl : public IDispatch\r
+    {\r
+    public:\r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Source( \r
+            /* [retval][out] */ BSTR *pstr) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_Source( \r
+            /* [in] */ BSTR str) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_IsLoaded( \r
+            /* [retval][out] */ VARIANT_BOOL *pb) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Content( \r
+            /* [retval][out] */ IDispatch **ppContent) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_Settings( \r
+            /* [retval][out] */ IDispatch **ppSettings) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnLoad( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnLoad( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnError( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnError( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE CreateObject( \r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE IsVersionSupported( \r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_InitParams( \r
+            /* [retval][out] */ BSTR *initparams) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_InitParams( \r
+            /* [in] */ BSTR initparams) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControl * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControl * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControl * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpControl * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpControl * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpControl * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpControl * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Source )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsLoaded )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ IDispatch **ppContent);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ IDispatch **ppSettings);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnLoad )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnLoad )( \r
+            IXcpControl * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnError )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnError )( \r
+            IXcpControl * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *CreateObject )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *IsVersionSupported )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InitParams )( \r
+            IXcpControl * This,\r
+            /* [retval][out] */ BSTR *initparams);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InitParams )( \r
+            IXcpControl * This,\r
+            /* [in] */ BSTR initparams);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlVtbl;\r
+\r
+    interface IXcpControl\r
+    {\r
+        CONST_VTBL struct IXcpControlVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControl_QueryInterface(This,riid,ppvObject)        \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControl_AddRef(This)       \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControl_Release(This)      \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControl_GetTypeInfoCount(This,pctinfo)     \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo)      \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)    \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)      \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#define IXcpControl_get_Source(This,pstr)      \\r
+    ( (This)->lpVtbl -> get_Source(This,pstr) ) \r
+\r
+#define IXcpControl_put_Source(This,str)       \\r
+    ( (This)->lpVtbl -> put_Source(This,str) ) \r
+\r
+#define IXcpControl_get_IsLoaded(This,pb)      \\r
+    ( (This)->lpVtbl -> get_IsLoaded(This,pb) ) \r
+\r
+#define IXcpControl_get_Content(This,ppContent)        \\r
+    ( (This)->lpVtbl -> get_Content(This,ppContent) ) \r
+\r
+#define IXcpControl_get_Settings(This,ppSettings)      \\r
+    ( (This)->lpVtbl -> get_Settings(This,ppSettings) ) \r
+\r
+#define IXcpControl_get_OnLoad(This,pVAR)      \\r
+    ( (This)->lpVtbl -> get_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl_put_OnLoad(This,pVAR)      \\r
+    ( (This)->lpVtbl -> put_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl_get_OnError(This,pVAR)     \\r
+    ( (This)->lpVtbl -> get_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl_put_OnError(This,pVAR)     \\r
+    ( (This)->lpVtbl -> put_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl_CreateObject(This,id,ppDisp)       \\r
+    ( (This)->lpVtbl -> CreateObject(This,id,ppDisp) ) \r
+\r
+#define IXcpControl_IsVersionSupported(This,v,pb)      \\r
+    ( (This)->lpVtbl -> IsVersionSupported(This,v,pb) ) \r
+\r
+#define IXcpControl_get_InitParams(This,initparams)    \\r
+    ( (This)->lpVtbl -> get_InitParams(This,initparams) ) \r
+\r
+#define IXcpControl_put_InitParams(This,initparams)    \\r
+    ( (This)->lpVtbl -> put_InitParams(This,initparams) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControl_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControl2_INTERFACE_DEFINED__\r
+#define __IXcpControl2_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControl2 */\r
+/* [unique][helpstring][nonextensible][dual][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControl2;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1c3294f9-891f-49b1-bbae-492a68ba10cc")\r
+    IXcpControl2 : public IXcpControl\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE LoadRuntime( void) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_SplashScreenSource( \r
+            /* [retval][out] */ BSTR *pstr) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_SplashScreenSource( \r
+            /* [in] */ BSTR str) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnSourceDownloadComplete( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnSourceDownloadComplete( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propget] */ HRESULT STDMETHODCALLTYPE get_OnSourceDownloadProgressChanged( \r
+            /* [retval][out] */ VARIANT *pVAR) = 0;\r
+        \r
+        virtual /* [requestedit][bindable][propput] */ HRESULT STDMETHODCALLTYPE put_OnSourceDownloadProgressChanged( \r
+            /* [in] */ VARIANT *pVAR) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControl2Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControl2 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControl2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( \r
+            IXcpControl2 * This,\r
+            /* [out] */ UINT *pctinfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ UINT iTInfo,\r
+            /* [in] */ LCID lcid,\r
+            /* [out] */ ITypeInfo **ppTInfo);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [size_is][in] */ LPOLESTR *rgszNames,\r
+            /* [range][in] */ UINT cNames,\r
+            /* [in] */ LCID lcid,\r
+            /* [size_is][out] */ DISPID *rgDispId);\r
+        \r
+        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ DISPID dispIdMember,\r
+            /* [in] */ REFIID riid,\r
+            /* [in] */ LCID lcid,\r
+            /* [in] */ WORD wFlags,\r
+            /* [out][in] */ DISPPARAMS *pDispParams,\r
+            /* [out] */ VARIANT *pVarResult,\r
+            /* [out] */ EXCEPINFO *pExcepInfo,\r
+            /* [out] */ UINT *puArgErr);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Source )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsLoaded )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ IDispatch **ppContent);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ IDispatch **ppSettings);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnLoad )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnLoad )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnError )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnError )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *CreateObject )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR id,\r
+            /* [retval][out] */ IXcpObject **ppDisp);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *IsVersionSupported )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR v,\r
+            /* [retval][out] */ VARIANT_BOOL *pb);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InitParams )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *initparams);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_InitParams )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR initparams);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *LoadRuntime )( \r
+            IXcpControl2 * This);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SplashScreenSource )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ BSTR *pstr);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SplashScreenSource )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ BSTR str);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnSourceDownloadComplete )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnSourceDownloadComplete )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OnSourceDownloadProgressChanged )( \r
+            IXcpControl2 * This,\r
+            /* [retval][out] */ VARIANT *pVAR);\r
+        \r
+        /* [requestedit][bindable][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OnSourceDownloadProgressChanged )( \r
+            IXcpControl2 * This,\r
+            /* [in] */ VARIANT *pVAR);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControl2Vtbl;\r
+\r
+    interface IXcpControl2\r
+    {\r
+        CONST_VTBL struct IXcpControl2Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControl2_QueryInterface(This,riid,ppvObject)       \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControl2_AddRef(This)      \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControl2_Release(This)     \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControl2_GetTypeInfoCount(This,pctinfo)    \\r
+    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) \r
+\r
+#define IXcpControl2_GetTypeInfo(This,iTInfo,lcid,ppTInfo)     \\r
+    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) \r
+\r
+#define IXcpControl2_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)   \\r
+    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) \r
+\r
+#define IXcpControl2_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)     \\r
+    ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) \r
+\r
+\r
+#define IXcpControl2_get_Source(This,pstr)     \\r
+    ( (This)->lpVtbl -> get_Source(This,pstr) ) \r
+\r
+#define IXcpControl2_put_Source(This,str)      \\r
+    ( (This)->lpVtbl -> put_Source(This,str) ) \r
+\r
+#define IXcpControl2_get_IsLoaded(This,pb)     \\r
+    ( (This)->lpVtbl -> get_IsLoaded(This,pb) ) \r
+\r
+#define IXcpControl2_get_Content(This,ppContent)       \\r
+    ( (This)->lpVtbl -> get_Content(This,ppContent) ) \r
+\r
+#define IXcpControl2_get_Settings(This,ppSettings)     \\r
+    ( (This)->lpVtbl -> get_Settings(This,ppSettings) ) \r
+\r
+#define IXcpControl2_get_OnLoad(This,pVAR)     \\r
+    ( (This)->lpVtbl -> get_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnLoad(This,pVAR)     \\r
+    ( (This)->lpVtbl -> put_OnLoad(This,pVAR) ) \r
+\r
+#define IXcpControl2_get_OnError(This,pVAR)    \\r
+    ( (This)->lpVtbl -> get_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnError(This,pVAR)    \\r
+    ( (This)->lpVtbl -> put_OnError(This,pVAR) ) \r
+\r
+#define IXcpControl2_CreateObject(This,id,ppDisp)      \\r
+    ( (This)->lpVtbl -> CreateObject(This,id,ppDisp) ) \r
+\r
+#define IXcpControl2_IsVersionSupported(This,v,pb)     \\r
+    ( (This)->lpVtbl -> IsVersionSupported(This,v,pb) ) \r
+\r
+#define IXcpControl2_get_InitParams(This,initparams)   \\r
+    ( (This)->lpVtbl -> get_InitParams(This,initparams) ) \r
+\r
+#define IXcpControl2_put_InitParams(This,initparams)   \\r
+    ( (This)->lpVtbl -> put_InitParams(This,initparams) ) \r
+\r
+\r
+#define IXcpControl2_LoadRuntime(This) \\r
+    ( (This)->lpVtbl -> LoadRuntime(This) ) \r
+\r
+#define IXcpControl2_get_SplashScreenSource(This,pstr) \\r
+    ( (This)->lpVtbl -> get_SplashScreenSource(This,pstr) ) \r
+\r
+#define IXcpControl2_put_SplashScreenSource(This,str)  \\r
+    ( (This)->lpVtbl -> put_SplashScreenSource(This,str) ) \r
+\r
+#define IXcpControl2_get_OnSourceDownloadComplete(This,pVAR)   \\r
+    ( (This)->lpVtbl -> get_OnSourceDownloadComplete(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnSourceDownloadComplete(This,pVAR)   \\r
+    ( (This)->lpVtbl -> put_OnSourceDownloadComplete(This,pVAR) ) \r
+\r
+#define IXcpControl2_get_OnSourceDownloadProgressChanged(This,pVAR)    \\r
+    ( (This)->lpVtbl -> get_OnSourceDownloadProgressChanged(This,pVAR) ) \r
+\r
+#define IXcpControl2_put_OnSourceDownloadProgressChanged(This,pVAR)    \\r
+    ( (This)->lpVtbl -> put_OnSourceDownloadProgressChanged(This,pVAR) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControl2_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlDownloadCallback_INTERFACE_DEFINED__\r
+#define __IXcpControlDownloadCallback_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlDownloadCallback */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlDownloadCallback;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("2E340632-5D5A-427b-AC31-303F6E32B9E8")\r
+    IXcpControlDownloadCallback : public IUnknown\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE OnUrlDownloaded( \r
+            HRESULT hr,\r
+            IStream *pStream) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlDownloadCallbackVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlDownloadCallback * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlDownloadCallback * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlDownloadCallback * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *OnUrlDownloaded )( \r
+            IXcpControlDownloadCallback * This,\r
+            HRESULT hr,\r
+            IStream *pStream);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlDownloadCallbackVtbl;\r
+\r
+    interface IXcpControlDownloadCallback\r
+    {\r
+        CONST_VTBL struct IXcpControlDownloadCallbackVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlDownloadCallback_QueryInterface(This,riid,ppvObject)        \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlDownloadCallback_AddRef(This)       \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlDownloadCallback_Release(This)      \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlDownloadCallback_OnUrlDownloaded(This,hr,pStream)   \\r
+    ( (This)->lpVtbl -> OnUrlDownloaded(This,hr,pStream) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlDownloadCallback_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost_INTERFACE_DEFINED__\r
+#define __IXcpControlHost_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+typedef /* [public] */ \r
+enum __MIDL_IXcpControlHost_0001\r
+    {  XcpHostOption_FreezeOnInitialFrame      = 0x1,\r
+       XcpHostOption_DisableFullScreen = 0x2,\r
+       XcpHostOption_DisableManagedExecution   = 0x8,\r
+       XcpHostOption_EnableCrossDomainDownloads        = 0x10,\r
+       XcpHostOption_UseCustomAppDomain        = 0x20,\r
+       XcpHostOption_DisableNetworking = 0x40,\r
+       XcpHostOption_DisableScriptCallouts     = 0x80,\r
+       XcpHostOption_EnableHtmlDomAccess       = 0x100,\r
+       XcpHostOption_EnableScriptableObjectAccess      = 0x200,\r
+       XcpHostOption_EnableAssemblySharing     = 0x800,\r
+       XcpHostOption_HookGetComAutomationObject        = 0x1000,\r
+       XcpHostOption_EnableElevatedPermissions = 0x2000,\r
+       XcpHostOption_EnableWindowlessAccessibility     = 0x4000\r
+    }  XcpHostOptions;\r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("1B36028E-B491-4bb2-8584-8A9E0A677D6E")\r
+    IXcpControlHost : public IUnknown\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetHostOptions( \r
+            /* [retval][out] */ DWORD *pdwOptions) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE NotifyLoaded( void) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE NotifyError( \r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE InvokeHandler( \r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetBaseUrl( \r
+            /* [retval][out] */ BSTR *pbstrUrl) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetNamedSource( \r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE DownloadUrl( \r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHostVtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHostVtbl;\r
+\r
+    interface IXcpControlHost\r
+    {\r
+        CONST_VTBL struct IXcpControlHostVtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost_QueryInterface(This,riid,ppvObject)    \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost_AddRef(This)   \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost_Release(This)  \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost_GetHostOptions(This,pdwOptions)        \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost_NotifyLoaded(This)     \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost_NotifyError(This,bstrError,bstrSource,nLine,nColumn)   \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)        \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost_GetBaseUrl(This,pbstrUrl)      \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost_GetNamedSource(This,bstrSourceName,pbstrSource)        \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost_DownloadUrl(This,bstrUrl,pCallback,ppStream)   \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost2_INTERFACE_DEFINED__\r
+#define __IXcpControlHost2_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost2 */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost2;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("fb3ed7c4-5797-4b44-8695-0c512ea27d8f")\r
+    IXcpControlHost2 : public IXcpControlHost\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetCustomAppDomain( \r
+            /* [retval][out] */ IUnknown **ppAppDomain) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetControlVersion( \r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHost2Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost2 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost2 * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetCustomAppDomain )( \r
+            IXcpControlHost2 * This,\r
+            /* [retval][out] */ IUnknown **ppAppDomain);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetControlVersion )( \r
+            IXcpControlHost2 * This,\r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHost2Vtbl;\r
+\r
+    interface IXcpControlHost2\r
+    {\r
+        CONST_VTBL struct IXcpControlHost2Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost2_QueryInterface(This,riid,ppvObject)   \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost2_AddRef(This)  \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost2_Release(This) \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost2_GetHostOptions(This,pdwOptions)       \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost2_NotifyLoaded(This)    \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost2_NotifyError(This,bstrError,bstrSource,nLine,nColumn)  \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost2_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)       \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost2_GetBaseUrl(This,pbstrUrl)     \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost2_GetNamedSource(This,bstrSourceName,pbstrSource)       \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost2_DownloadUrl(This,bstrUrl,pCallback,ppStream)  \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+\r
+#define IXcpControlHost2_GetCustomAppDomain(This,ppAppDomain)  \\r
+    ( (This)->lpVtbl -> GetCustomAppDomain(This,ppAppDomain) ) \r
+\r
+#define IXcpControlHost2_GetControlVersion(This,puMajorVersion,puMinorVersion) \\r
+    ( (This)->lpVtbl -> GetControlVersion(This,puMajorVersion,puMinorVersion) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost2_INTERFACE_DEFINED__ */\r
+\r
+\r
+#ifndef __IXcpControlHost3_INTERFACE_DEFINED__\r
+#define __IXcpControlHost3_INTERFACE_DEFINED__\r
+\r
+/* interface IXcpControlHost3 */\r
+/* [unique][helpstring][nonextensible][uuid][object] */ \r
+\r
+typedef /* [public] */ \r
+enum __MIDL_IXcpControlHost3_0001\r
+    {  XcpHost_GetComAutomationObjectFlag_Get  = 0x1,\r
+       XcpHost_GetComAutomationObjectFlag_Create       = 0x2\r
+    }  XcpHost_GetComAutomationObjectFlags;\r
+\r
+\r
+EXTERN_C const IID IID_IXcpControlHost3;\r
+\r
+#if defined(__cplusplus) && !defined(CINTERFACE)\r
+    \r
+    MIDL_INTERFACE("9fb2ce5f-06ff-4058-befa-ddfab596b3d5")\r
+    IXcpControlHost3 : public IXcpControlHost2\r
+    {\r
+    public:\r
+        virtual HRESULT STDMETHODCALLTYPE GetDefaultThemeXaml( \r
+            /* [in] */ BSTR assemblyName,\r
+            /* [retval][out] */ LPBSTR pbstrXaml) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetDefaultPortableUserInterfaceFontInfo( \r
+            /* [retval][out] */ LPBSTR pbstrCompositeFont) = 0;\r
+        \r
+        virtual HRESULT STDMETHODCALLTYPE GetComAutomationObject( \r
+            /* [in] */ BSTR bstrProgId,\r
+            /* [in] */ DWORD dwFlags,\r
+            /* [retval][out] */ IDispatch **ppDisp) = 0;\r
+        \r
+    };\r
+    \r
+#else  /* C style interface */\r
+\r
+    typedef struct IXcpControlHost3Vtbl\r
+    {\r
+        BEGIN_INTERFACE\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ REFIID riid,\r
+            /* [annotation][iid_is][out] */ \r
+            __RPC__deref_out  void **ppvObject);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *AddRef )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        ULONG ( STDMETHODCALLTYPE *Release )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetHostOptions )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ DWORD *pdwOptions);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyLoaded )( \r
+            IXcpControlHost3 * This);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *NotifyError )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrError,\r
+            /* [in] */ BSTR bstrSource,\r
+            /* [in] */ long nLine,\r
+            /* [in] */ long nColumn);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *InvokeHandler )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrName,\r
+            /* [in] */ VARIANT varArg1,\r
+            /* [in] */ VARIANT varArg2,\r
+            /* [retval][out] */ VARIANT *pvarResult);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetBaseUrl )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ BSTR *pbstrUrl);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetNamedSource )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrSourceName,\r
+            /* [retval][out] */ BSTR *pbstrSource);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *DownloadUrl )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrUrl,\r
+            /* [in] */ IXcpControlDownloadCallback *pCallback,\r
+            /* [retval][out] */ IStream **ppStream);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetCustomAppDomain )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ IUnknown **ppAppDomain);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetControlVersion )( \r
+            IXcpControlHost3 * This,\r
+            /* [out] */ UINT *puMajorVersion,\r
+            /* [out] */ UINT *puMinorVersion);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetDefaultThemeXaml )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR assemblyName,\r
+            /* [retval][out] */ LPBSTR pbstrXaml);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetDefaultPortableUserInterfaceFontInfo )( \r
+            IXcpControlHost3 * This,\r
+            /* [retval][out] */ LPBSTR pbstrCompositeFont);\r
+        \r
+        HRESULT ( STDMETHODCALLTYPE *GetComAutomationObject )( \r
+            IXcpControlHost3 * This,\r
+            /* [in] */ BSTR bstrProgId,\r
+            /* [in] */ DWORD dwFlags,\r
+            /* [retval][out] */ IDispatch **ppDisp);\r
+        \r
+        END_INTERFACE\r
+    } IXcpControlHost3Vtbl;\r
+\r
+    interface IXcpControlHost3\r
+    {\r
+        CONST_VTBL struct IXcpControlHost3Vtbl *lpVtbl;\r
+    };\r
+\r
+    \r
+\r
+#ifdef COBJMACROS\r
+\r
+\r
+#define IXcpControlHost3_QueryInterface(This,riid,ppvObject)   \\r
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r
+\r
+#define IXcpControlHost3_AddRef(This)  \\r
+    ( (This)->lpVtbl -> AddRef(This) ) \r
+\r
+#define IXcpControlHost3_Release(This) \\r
+    ( (This)->lpVtbl -> Release(This) ) \r
+\r
+\r
+#define IXcpControlHost3_GetHostOptions(This,pdwOptions)       \\r
+    ( (This)->lpVtbl -> GetHostOptions(This,pdwOptions) ) \r
+\r
+#define IXcpControlHost3_NotifyLoaded(This)    \\r
+    ( (This)->lpVtbl -> NotifyLoaded(This) ) \r
+\r
+#define IXcpControlHost3_NotifyError(This,bstrError,bstrSource,nLine,nColumn)  \\r
+    ( (This)->lpVtbl -> NotifyError(This,bstrError,bstrSource,nLine,nColumn) ) \r
+\r
+#define IXcpControlHost3_InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult)       \\r
+    ( (This)->lpVtbl -> InvokeHandler(This,bstrName,varArg1,varArg2,pvarResult) ) \r
+\r
+#define IXcpControlHost3_GetBaseUrl(This,pbstrUrl)     \\r
+    ( (This)->lpVtbl -> GetBaseUrl(This,pbstrUrl) ) \r
+\r
+#define IXcpControlHost3_GetNamedSource(This,bstrSourceName,pbstrSource)       \\r
+    ( (This)->lpVtbl -> GetNamedSource(This,bstrSourceName,pbstrSource) ) \r
+\r
+#define IXcpControlHost3_DownloadUrl(This,bstrUrl,pCallback,ppStream)  \\r
+    ( (This)->lpVtbl -> DownloadUrl(This,bstrUrl,pCallback,ppStream) ) \r
+\r
+\r
+#define IXcpControlHost3_GetCustomAppDomain(This,ppAppDomain)  \\r
+    ( (This)->lpVtbl -> GetCustomAppDomain(This,ppAppDomain) ) \r
+\r
+#define IXcpControlHost3_GetControlVersion(This,puMajorVersion,puMinorVersion) \\r
+    ( (This)->lpVtbl -> GetControlVersion(This,puMajorVersion,puMinorVersion) ) \r
+\r
+\r
+#define IXcpControlHost3_GetDefaultThemeXaml(This,assemblyName,pbstrXaml)      \\r
+    ( (This)->lpVtbl -> GetDefaultThemeXaml(This,assemblyName,pbstrXaml) ) \r
+\r
+#define IXcpControlHost3_GetDefaultPortableUserInterfaceFontInfo(This,pbstrCompositeFont)      \\r
+    ( (This)->lpVtbl -> GetDefaultPortableUserInterfaceFontInfo(This,pbstrCompositeFont) ) \r
+\r
+#define IXcpControlHost3_GetComAutomationObject(This,bstrProgId,dwFlags,ppDisp)        \\r
+    ( (This)->lpVtbl -> GetComAutomationObject(This,bstrProgId,dwFlags,ppDisp) ) \r
+\r
+#endif /* COBJMACROS */\r
+\r
+\r
+#endif         /* C style interface */\r
+\r
+\r
+\r
+\r
+#endif         /* __IXcpControlHost3_INTERFACE_DEFINED__ */\r
+\r
+\r
+\r
+#ifndef __XcpControlLib_LIBRARY_DEFINED__\r
+#define __XcpControlLib_LIBRARY_DEFINED__\r
+\r
+/* library XcpControlLib */\r
+/* [control][helpstring][version][uuid] */ \r
+\r
+\r
+EXTERN_C const IID LIBID_XcpControlLib;\r
+\r
+EXTERN_C const CLSID CLSID_XcpControl;\r
+\r
+#ifdef __cplusplus\r
+\r
+class DECLSPEC_UUID("DFEAF541-F3E1-4c24-ACAC-99C30715084A")\r
+XcpControl;\r
+#endif\r
+#endif /* __XcpControlLib_LIBRARY_DEFINED__ */\r
+\r
+/* Additional Prototypes for ALL interfaces */\r
+\r
+unsigned long             __RPC_USER  BSTR_UserSize(     unsigned long *, unsigned long            , BSTR * ); \r
+unsigned char * __RPC_USER  BSTR_UserMarshal(  unsigned long *, unsigned char *, BSTR * ); \r
+unsigned char * __RPC_USER  BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); \r
+void                      __RPC_USER  BSTR_UserFree(     unsigned long *, BSTR * ); \r
+\r
+unsigned long             __RPC_USER  VARIANT_UserSize(     unsigned long *, unsigned long            , VARIANT * ); \r
+unsigned char * __RPC_USER  VARIANT_UserMarshal(  unsigned long *, unsigned char *, VARIANT * ); \r
+unsigned char * __RPC_USER  VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); \r
+void                      __RPC_USER  VARIANT_UserFree(     unsigned long *, VARIANT * ); \r
+\r
+/* end of Additional Prototypes */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
diff --git a/modules/silverlight/interop/xcpctrl_i.c b/modules/silverlight/interop/xcpctrl_i.c
new file mode 100644 (file)
index 0000000..e6a25ca
--- /dev/null
@@ -0,0 +1,103 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */\r
+\r
+/* link this file in with the server and any clients */\r
+\r
+\r
+ /* File created by MIDL compiler version 7.00.0555 */\r
+/* at Sat Jan 22 19:55:15 2011\r
+ */\r
+/* Compiler settings for xcpctrl.idl:\r
+    Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+/* @@MIDL_FILE_HEADING(  ) */\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif \r
+\r
+\r
+#include <rpc.h>\r
+#include <rpcndr.h>\r
+\r
+#ifdef _MIDL_USE_GUIDDEF_\r
+\r
+#ifndef INITGUID\r
+#define INITGUID\r
+#include <guiddef.h>\r
+#undef INITGUID\r
+#else\r
+#include <guiddef.h>\r
+#endif\r
+\r
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\r
+        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\r
+\r
+#else // !_MIDL_USE_GUIDDEF_\r
+\r
+#ifndef __IID_DEFINED__\r
+#define __IID_DEFINED__\r
+\r
+typedef struct _IID\r
+{\r
+    unsigned long x;\r
+    unsigned short s1;\r
+    unsigned short s2;\r
+    unsigned char  c[8];\r
+} IID;\r
+\r
+#endif // __IID_DEFINED__\r
+\r
+#ifndef CLSID_DEFINED\r
+#define CLSID_DEFINED\r
+typedef IID CLSID;\r
+#endif // CLSID_DEFINED\r
+\r
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\r
+        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\r
+\r
+#endif !_MIDL_USE_GUIDDEF_\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpObject,0xEE38D0F1,0x5AE3,0x408c,0xA6,0xBF,0x84,0x10,0xE6,0x45,0xF3,0x76);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControl,0x1FB839CC,0x116C,0x4C9B,0xAE,0x8E,0x3D,0xBB,0x64,0x96,0xE3,0x26);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControl2,0x1c3294f9,0x891f,0x49b1,0xbb,0xae,0x49,0x2a,0x68,0xba,0x10,0xcc);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControlDownloadCallback,0x2E340632,0x5D5A,0x427b,0xAC,0x31,0x30,0x3F,0x6E,0x32,0xB9,0xE8);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControlHost,0x1B36028E,0xB491,0x4bb2,0x85,0x84,0x8A,0x9E,0x0A,0x67,0x7D,0x6E);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControlHost2,0xfb3ed7c4,0x5797,0x4b44,0x86,0x95,0x0c,0x51,0x2e,0xa2,0x7d,0x8f);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, IID_IXcpControlHost3,0x9fb2ce5f,0x06ff,0x4058,0xbe,0xfa,0xdd,0xfa,0xb5,0x96,0xb3,0xd5);\r
+\r
+\r
+MIDL_DEFINE_GUID(IID, LIBID_XcpControlLib,0x283C8576,0x0726,0x4DBC,0x96,0x09,0x3F,0x85,0x51,0x62,0x00,0x9A);\r
+\r
+\r
+MIDL_DEFINE_GUID(CLSID, CLSID_XcpControl,0xDFEAF541,0xF3E1,0x4c24,0xAC,0xAC,0x99,0xC3,0x07,0x15,0x08,0x4A);\r
+\r
+#undef MIDL_DEFINE_GUID\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+\r
diff --git a/modules/silverlight/interop/xcpctrl_p.c b/modules/silverlight/interop/xcpctrl_p.c
new file mode 100644 (file)
index 0000000..1ea6d74
--- /dev/null
@@ -0,0 +1,2700 @@
+\r
+\r
+/* this ALWAYS GENERATED file contains the proxy stub code */\r
+\r
+\r
+ /* File created by MIDL compiler version 7.00.0555 */\r
+/* at Sat Jan 22 19:55:15 2011\r
+ */\r
+/* Compiler settings for xcpctrl.idl:\r
+    Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
+    protocol : dce , ms_ext, c_ext, robust\r
+    error checks: allocation ref bounds_check enum stub_data \r
+    VC __declspec() decoration level: \r
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r
+         DECLSPEC_UUID(), MIDL_INTERFACE()\r
+*/\r
+/* @@MIDL_FILE_HEADING(  ) */\r
+\r
+#if !defined(_M_IA64) && !defined(_M_AMD64)\r
+\r
+\r
+#pragma warning( disable: 4049 )  /* more than 64k source lines */\r
+#if _MSC_VER >= 1200\r
+#pragma warning(push)\r
+#endif\r
+\r
+#pragma warning( disable: 4211 )  /* redefine extern to static */\r
+#pragma warning( disable: 4232 )  /* dllimport identity*/\r
+#pragma warning( disable: 4024 )  /* array to pointer mapping*/\r
+#pragma warning( disable: 4152 )  /* function/data pointer conversion in expression */\r
+#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */\r
+\r
+#pragma optimize("", off ) \r
+\r
+#define USE_STUBLESS_PROXY\r
+\r
+\r
+/* verify that the <rpcproxy.h> version is high enough to compile this file*/\r
+#ifndef __REDQ_RPCPROXY_H_VERSION__\r
+#define __REQUIRED_RPCPROXY_H_VERSION__ 475\r
+#endif\r
+\r
+\r
+#include "rpcproxy.h"\r
+#ifndef __RPCPROXY_H_VERSION__\r
+#error this stub requires an updated version of <rpcproxy.h>\r
+#endif /* __RPCPROXY_H_VERSION__ */\r
+\r
+\r
+#include "xcpctrl_h.h"\r
+\r
+#define TYPE_FORMAT_STRING_SIZE   1163                              \r
+#define PROC_FORMAT_STRING_SIZE   1237                              \r
+#define EXPR_FORMAT_STRING_SIZE   1                                 \r
+#define TRANSMIT_AS_TABLE_SIZE    0            \r
+#define WIRE_MARSHAL_TABLE_SIZE   2            \r
+\r
+typedef struct _xcpctrl_MIDL_TYPE_FORMAT_STRING\r
+    {\r
+    short          Pad;\r
+    unsigned char  Format[ TYPE_FORMAT_STRING_SIZE ];\r
+    } xcpctrl_MIDL_TYPE_FORMAT_STRING;\r
+\r
+typedef struct _xcpctrl_MIDL_PROC_FORMAT_STRING\r
+    {\r
+    short          Pad;\r
+    unsigned char  Format[ PROC_FORMAT_STRING_SIZE ];\r
+    } xcpctrl_MIDL_PROC_FORMAT_STRING;\r
+\r
+typedef struct _xcpctrl_MIDL_EXPR_FORMAT_STRING\r
+    {\r
+    long          Pad;\r
+    unsigned char  Format[ EXPR_FORMAT_STRING_SIZE ];\r
+    } xcpctrl_MIDL_EXPR_FORMAT_STRING;\r
+\r
+\r
+static const RPC_SYNTAX_IDENTIFIER  _RpcTransferSyntax = \r
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};\r
+\r
+\r
+extern const xcpctrl_MIDL_TYPE_FORMAT_STRING xcpctrl__MIDL_TypeFormatString;\r
+extern const xcpctrl_MIDL_PROC_FORMAT_STRING xcpctrl__MIDL_ProcFormatString;\r
+extern const xcpctrl_MIDL_EXPR_FORMAT_STRING xcpctrl__MIDL_ExprFormatString;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpObject_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpObject_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControl_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControl_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControl2_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControl2_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControlDownloadCallback_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControlDownloadCallback_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControlHost_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControlHost_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControlHost2_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControlHost2_ProxyInfo;\r
+\r
+\r
+extern const MIDL_STUB_DESC Object_StubDesc;\r
+\r
+\r
+extern const MIDL_SERVER_INFO IXcpControlHost3_ServerInfo;\r
+extern const MIDL_STUBLESS_PROXY_INFO IXcpControlHost3_ProxyInfo;\r
+\r
+\r
+extern const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ];\r
+\r
+#if !defined(__RPC_WIN32__)\r
+#error  Invalid build platform for this stub.\r
+#endif\r
+\r
+#if !(TARGET_IS_NT50_OR_LATER)\r
+#error You need Windows 2000 or later to run this stub because it uses these features:\r
+#error   /robust command line switch.\r
+#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.\r
+#error This app will fail with the RPC_X_WRONG_STUB_VERSION error.\r
+#endif\r
+\r
+\r
+static const xcpctrl_MIDL_PROC_FORMAT_STRING xcpctrl__MIDL_ProcFormatString =\r
+    {\r
+        0,\r
+        {\r
+\r
+       /* Procedure GetBaseUrl */\r
+\r
+\r
+       /* Procedure get_Source */\r
+\r
+                       0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/*  2 */       NdrFcLong( 0x0 ),       /* 0 */\r
+/*  6 */       NdrFcShort( 0x7 ),      /* 7 */\r
+/*  8 */       NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 10 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 12 */       NdrFcShort( 0x8 ),      /* 8 */\r
+/* 14 */       0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 16 */       0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 18 */       NdrFcShort( 0x1 ),      /* 1 */\r
+/* 20 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 22 */       NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pbstrUrl */\r
+\r
+\r
+       /* Parameter pstr */\r
+\r
+/* 24 */       NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 26 */       NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 28 */       NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+\r
+       /* Return value */\r
+\r
+/* 30 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 32 */       NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 34 */       0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_Source */\r
+\r
+/* 36 */       0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 38 */       NdrFcLong( 0x0 ),       /* 0 */\r
+/* 42 */       NdrFcShort( 0x8 ),      /* 8 */\r
+/* 44 */       NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 46 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 48 */       NdrFcShort( 0x8 ),      /* 8 */\r
+/* 50 */       0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 52 */       0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 54 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 56 */       NdrFcShort( 0x1 ),      /* 1 */\r
+/* 58 */       NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter str */\r
+\r
+/* 60 */       NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 62 */       NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 64 */       NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Return value */\r
+\r
+/* 66 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 68 */       NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 70 */       0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_IsLoaded */\r
+\r
+/* 72 */       0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 74 */       NdrFcLong( 0x0 ),       /* 0 */\r
+/* 78 */       NdrFcShort( 0x9 ),      /* 9 */\r
+/* 80 */       NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 82 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 84 */       NdrFcShort( 0x22 ),     /* 34 */\r
+/* 86 */       0x44,           /* Oi2 Flags:  has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 88 */       0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 90 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 92 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 94 */       NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pb */\r
+\r
+/* 96 */       NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */\r
+/* 98 */       NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 100 */      0x6,            /* FC_SHORT */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 102 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 104 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 106 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_Content */\r
+\r
+/* 108 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 110 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 114 */      NdrFcShort( 0xa ),      /* 10 */\r
+/* 116 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 118 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 120 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 122 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 124 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 126 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 128 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 130 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter ppContent */\r
+\r
+/* 132 */      NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 134 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 136 */      NdrFcShort( 0x3c ),     /* Type Offset=60 */\r
+\r
+       /* Return value */\r
+\r
+/* 138 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 140 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 142 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_Settings */\r
+\r
+/* 144 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 146 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 150 */      NdrFcShort( 0xb ),      /* 11 */\r
+/* 152 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 154 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 156 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 158 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 160 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 162 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 164 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 166 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter ppSettings */\r
+\r
+/* 168 */      NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 170 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 172 */      NdrFcShort( 0x3c ),     /* Type Offset=60 */\r
+\r
+       /* Return value */\r
+\r
+/* 174 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 176 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 178 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_OnLoad */\r
+\r
+/* 180 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 182 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 186 */      NdrFcShort( 0xc ),      /* 12 */\r
+/* 188 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 190 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 192 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 194 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 196 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 198 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 200 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 202 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 204 */      NdrFcShort( 0x4113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=16 */\r
+/* 206 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 208 */      NdrFcShort( 0x428 ),    /* Type Offset=1064 */\r
+\r
+       /* Return value */\r
+\r
+/* 210 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 212 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 214 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_OnLoad */\r
+\r
+/* 216 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 218 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 222 */      NdrFcShort( 0xd ),      /* 13 */\r
+/* 224 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 226 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 228 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 230 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 232 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 234 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 236 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 238 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 240 */      NdrFcShort( 0x10b ),    /* Flags:  must size, must free, in, simple ref, */\r
+/* 242 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 244 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Return value */\r
+\r
+/* 246 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 248 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 250 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_OnError */\r
+\r
+/* 252 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 254 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 258 */      NdrFcShort( 0xe ),      /* 14 */\r
+/* 260 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 262 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 264 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 266 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 268 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 270 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 272 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 274 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 276 */      NdrFcShort( 0x4113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=16 */\r
+/* 278 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 280 */      NdrFcShort( 0x428 ),    /* Type Offset=1064 */\r
+\r
+       /* Return value */\r
+\r
+/* 282 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 284 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 286 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_OnError */\r
+\r
+/* 288 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 290 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 294 */      NdrFcShort( 0xf ),      /* 15 */\r
+/* 296 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 298 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 300 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 302 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 304 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 306 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 308 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 310 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 312 */      NdrFcShort( 0x10b ),    /* Flags:  must size, must free, in, simple ref, */\r
+/* 314 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 316 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Return value */\r
+\r
+/* 318 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 320 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 322 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure CreateObject */\r
+\r
+/* 324 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 326 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 330 */      NdrFcShort( 0x10 ),     /* 16 */\r
+/* 332 */      NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 334 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 336 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 338 */      0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 340 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 342 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 344 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 346 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter id */\r
+\r
+/* 348 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 350 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 352 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter ppDisp */\r
+\r
+/* 354 */      NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 356 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 358 */      NdrFcShort( 0x444 ),    /* Type Offset=1092 */\r
+\r
+       /* Return value */\r
+\r
+/* 360 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 362 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 364 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure IsVersionSupported */\r
+\r
+/* 366 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 368 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 372 */      NdrFcShort( 0x11 ),     /* 17 */\r
+/* 374 */      NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 376 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 378 */      NdrFcShort( 0x22 ),     /* 34 */\r
+/* 380 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 382 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 384 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 386 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 388 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter v */\r
+\r
+/* 390 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 392 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 394 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter pb */\r
+\r
+/* 396 */      NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */\r
+/* 398 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 400 */      0x6,            /* FC_SHORT */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 402 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 404 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 406 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_InitParams */\r
+\r
+/* 408 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 410 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 414 */      NdrFcShort( 0x12 ),     /* 18 */\r
+/* 416 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 418 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 420 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 422 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 424 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 426 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 428 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 430 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter initparams */\r
+\r
+/* 432 */      NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 434 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 436 */      NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+/* 438 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 440 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 442 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_InitParams */\r
+\r
+/* 444 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 446 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 450 */      NdrFcShort( 0x13 ),     /* 19 */\r
+/* 452 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 454 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 456 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 458 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 460 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 462 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 464 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 466 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter initparams */\r
+\r
+/* 468 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 470 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 472 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Return value */\r
+\r
+/* 474 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 476 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 478 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure LoadRuntime */\r
+\r
+/* 480 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 482 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 486 */      NdrFcShort( 0x14 ),     /* 20 */\r
+/* 488 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 490 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 492 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 494 */      0x44,           /* Oi2 Flags:  has return, has ext, */\r
+                       0x1,            /* 1 */\r
+/* 496 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 498 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 500 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 502 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 504 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 506 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 508 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_SplashScreenSource */\r
+\r
+/* 510 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 512 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 516 */      NdrFcShort( 0x15 ),     /* 21 */\r
+/* 518 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 520 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 522 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 524 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 526 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 528 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 530 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 532 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pstr */\r
+\r
+/* 534 */      NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 536 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 538 */      NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+/* 540 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 542 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 544 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_SplashScreenSource */\r
+\r
+/* 546 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 548 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 552 */      NdrFcShort( 0x16 ),     /* 22 */\r
+/* 554 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 556 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 558 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 560 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 562 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 564 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 566 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 568 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter str */\r
+\r
+/* 570 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 572 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 574 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Return value */\r
+\r
+/* 576 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 578 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 580 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_OnSourceDownloadComplete */\r
+\r
+/* 582 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 584 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 588 */      NdrFcShort( 0x17 ),     /* 23 */\r
+/* 590 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 592 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 594 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 596 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 598 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 600 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 602 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 604 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 606 */      NdrFcShort( 0x4113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=16 */\r
+/* 608 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 610 */      NdrFcShort( 0x428 ),    /* Type Offset=1064 */\r
+\r
+       /* Return value */\r
+\r
+/* 612 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 614 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 616 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_OnSourceDownloadComplete */\r
+\r
+/* 618 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 620 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 624 */      NdrFcShort( 0x18 ),     /* 24 */\r
+/* 626 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 628 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 630 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 632 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 634 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 636 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 638 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 640 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 642 */      NdrFcShort( 0x10b ),    /* Flags:  must size, must free, in, simple ref, */\r
+/* 644 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 646 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Return value */\r
+\r
+/* 648 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 650 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 652 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure get_OnSourceDownloadProgressChanged */\r
+\r
+/* 654 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 656 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 660 */      NdrFcShort( 0x19 ),     /* 25 */\r
+/* 662 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 664 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 666 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 668 */      0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 670 */      0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 672 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 674 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 676 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 678 */      NdrFcShort( 0x4113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=16 */\r
+/* 680 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 682 */      NdrFcShort( 0x428 ),    /* Type Offset=1064 */\r
+\r
+       /* Return value */\r
+\r
+/* 684 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 686 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 688 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure put_OnSourceDownloadProgressChanged */\r
+\r
+/* 690 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 692 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 696 */      NdrFcShort( 0x1a ),     /* 26 */\r
+/* 698 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 700 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 702 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 704 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 706 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 708 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 710 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 712 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pVAR */\r
+\r
+/* 714 */      NdrFcShort( 0x10b ),    /* Flags:  must size, must free, in, simple ref, */\r
+/* 716 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 718 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Return value */\r
+\r
+/* 720 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 722 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 724 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure OnUrlDownloaded */\r
+\r
+/* 726 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 728 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 732 */      NdrFcShort( 0x3 ),      /* 3 */\r
+/* 734 */      NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 736 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 738 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 740 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 742 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 744 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 746 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 748 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter hr */\r
+\r
+/* 750 */      NdrFcShort( 0x48 ),     /* Flags:  in, base type, */\r
+/* 752 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 754 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Parameter pStream */\r
+\r
+/* 756 */      NdrFcShort( 0xb ),      /* Flags:  must size, must free, in, */\r
+/* 758 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 760 */      NdrFcShort( 0x45a ),    /* Type Offset=1114 */\r
+\r
+       /* Return value */\r
+\r
+/* 762 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 764 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 766 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetHostOptions */\r
+\r
+/* 768 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 770 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 774 */      NdrFcShort( 0x3 ),      /* 3 */\r
+/* 776 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 778 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 780 */      NdrFcShort( 0x24 ),     /* 36 */\r
+/* 782 */      0x44,           /* Oi2 Flags:  has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 784 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 786 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 788 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 790 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pdwOptions */\r
+\r
+/* 792 */      NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */\r
+/* 794 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 796 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 798 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 800 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 802 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure NotifyLoaded */\r
+\r
+/* 804 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 806 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 810 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 812 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 814 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 816 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 818 */      0x44,           /* Oi2 Flags:  has return, has ext, */\r
+                       0x1,            /* 1 */\r
+/* 820 */      0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 822 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 824 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 826 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 828 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 830 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 832 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure NotifyError */\r
+\r
+/* 834 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 836 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 840 */      NdrFcShort( 0x5 ),      /* 5 */\r
+/* 842 */      NdrFcShort( 0x18 ),     /* x86 Stack size/offset = 24 */\r
+/* 844 */      NdrFcShort( 0x10 ),     /* 16 */\r
+/* 846 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 848 */      0x46,           /* Oi2 Flags:  clt must size, has return, has ext, */\r
+                       0x5,            /* 5 */\r
+/* 850 */      0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 852 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 854 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 856 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter bstrError */\r
+\r
+/* 858 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 860 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 862 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter bstrSource */\r
+\r
+/* 864 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 866 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 868 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter nLine */\r
+\r
+/* 870 */      NdrFcShort( 0x48 ),     /* Flags:  in, base type, */\r
+/* 872 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 874 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Parameter nColumn */\r
+\r
+/* 876 */      NdrFcShort( 0x48 ),     /* Flags:  in, base type, */\r
+/* 878 */      NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 880 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 882 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 884 */      NdrFcShort( 0x14 ),     /* x86 Stack size/offset = 20 */\r
+/* 886 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure InvokeHandler */\r
+\r
+/* 888 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 890 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 894 */      NdrFcShort( 0x6 ),      /* 6 */\r
+/* 896 */      NdrFcShort( 0x30 ),     /* x86 Stack size/offset = 48 */\r
+/* 898 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 900 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 902 */      0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x5,            /* 5 */\r
+/* 904 */      0x8,            /* 8 */\r
+                       0x7,            /* Ext Flags:  new corr desc, clt corr check, srv corr check, */\r
+/* 906 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 908 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 910 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter bstrName */\r
+\r
+/* 912 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 914 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 916 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter varArg1 */\r
+\r
+/* 918 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 920 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 922 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Parameter varArg2 */\r
+\r
+/* 924 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 926 */      NdrFcShort( 0x18 ),     /* x86 Stack size/offset = 24 */\r
+/* 928 */      NdrFcShort( 0x43a ),    /* Type Offset=1082 */\r
+\r
+       /* Parameter pvarResult */\r
+\r
+/* 930 */      NdrFcShort( 0x4113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=16 */\r
+/* 932 */      NdrFcShort( 0x28 ),     /* x86 Stack size/offset = 40 */\r
+/* 934 */      NdrFcShort( 0x428 ),    /* Type Offset=1064 */\r
+\r
+       /* Return value */\r
+\r
+/* 936 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 938 */      NdrFcShort( 0x2c ),     /* x86 Stack size/offset = 44 */\r
+/* 940 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetNamedSource */\r
+\r
+/* 942 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 944 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 948 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 950 */      NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 952 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 954 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 956 */      0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 958 */      0x8,            /* 8 */\r
+                       0x7,            /* Ext Flags:  new corr desc, clt corr check, srv corr check, */\r
+/* 960 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 962 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 964 */      NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter bstrSourceName */\r
+\r
+/* 966 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 968 */      NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 970 */      NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter pbstrSource */\r
+\r
+/* 972 */      NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 974 */      NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 976 */      NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+/* 978 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 980 */      NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 982 */      0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure DownloadUrl */\r
+\r
+/* 984 */      0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 986 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 990 */      NdrFcShort( 0x9 ),      /* 9 */\r
+/* 992 */      NdrFcShort( 0x14 ),     /* x86 Stack size/offset = 20 */\r
+/* 994 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 996 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 998 */      0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x4,            /* 4 */\r
+/* 1000 */     0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 1002 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1004 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1006 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter bstrUrl */\r
+\r
+/* 1008 */     NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 1010 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1012 */     NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter pCallback */\r
+\r
+/* 1014 */     NdrFcShort( 0xb ),      /* Flags:  must size, must free, in, */\r
+/* 1016 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1018 */     NdrFcShort( 0x470 ),    /* Type Offset=1136 */\r
+\r
+       /* Parameter ppStream */\r
+\r
+/* 1020 */     NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 1022 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1024 */     NdrFcShort( 0x482 ),    /* Type Offset=1154 */\r
+\r
+       /* Return value */\r
+\r
+/* 1026 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1028 */     NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 1030 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetCustomAppDomain */\r
+\r
+/* 1032 */     0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 1034 */     NdrFcLong( 0x0 ),       /* 0 */\r
+/* 1038 */     NdrFcShort( 0xa ),      /* 10 */\r
+/* 1040 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1042 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1044 */     NdrFcShort( 0x8 ),      /* 8 */\r
+/* 1046 */     0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 1048 */     0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 1050 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1052 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1054 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter ppAppDomain */\r
+\r
+/* 1056 */     NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 1058 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1060 */     NdrFcShort( 0x486 ),    /* Type Offset=1158 */\r
+\r
+       /* Return value */\r
+\r
+/* 1062 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1064 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1066 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetControlVersion */\r
+\r
+/* 1068 */     0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 1070 */     NdrFcLong( 0x0 ),       /* 0 */\r
+/* 1074 */     NdrFcShort( 0xb ),      /* 11 */\r
+/* 1076 */     NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 1078 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1080 */     NdrFcShort( 0x40 ),     /* 64 */\r
+/* 1082 */     0x44,           /* Oi2 Flags:  has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 1084 */     0x8,            /* 8 */\r
+                       0x1,            /* Ext Flags:  new corr desc, */\r
+/* 1086 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1088 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1090 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter puMajorVersion */\r
+\r
+/* 1092 */     NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */\r
+/* 1094 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1096 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Parameter puMinorVersion */\r
+\r
+/* 1098 */     NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */\r
+/* 1100 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1102 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Return value */\r
+\r
+/* 1104 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1106 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1108 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetDefaultThemeXaml */\r
+\r
+/* 1110 */     0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 1112 */     NdrFcLong( 0x0 ),       /* 0 */\r
+/* 1116 */     NdrFcShort( 0xc ),      /* 12 */\r
+/* 1118 */     NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 1120 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1122 */     NdrFcShort( 0x8 ),      /* 8 */\r
+/* 1124 */     0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x3,            /* 3 */\r
+/* 1126 */     0x8,            /* 8 */\r
+                       0x7,            /* Ext Flags:  new corr desc, clt corr check, srv corr check, */\r
+/* 1128 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1130 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1132 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter assemblyName */\r
+\r
+/* 1134 */     NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 1136 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1138 */     NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter pbstrXaml */\r
+\r
+/* 1140 */     NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 1142 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1144 */     NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+/* 1146 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1148 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1150 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetDefaultPortableUserInterfaceFontInfo */\r
+\r
+/* 1152 */     0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 1154 */     NdrFcLong( 0x0 ),       /* 0 */\r
+/* 1158 */     NdrFcShort( 0xd ),      /* 13 */\r
+/* 1160 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1162 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1164 */     NdrFcShort( 0x8 ),      /* 8 */\r
+/* 1166 */     0x45,           /* Oi2 Flags:  srv must size, has return, has ext, */\r
+                       0x2,            /* 2 */\r
+/* 1168 */     0x8,            /* 8 */\r
+                       0x3,            /* Ext Flags:  new corr desc, clt corr check, */\r
+/* 1170 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1172 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1174 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter pbstrCompositeFont */\r
+\r
+/* 1176 */     NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */\r
+/* 1178 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1180 */     NdrFcShort( 0x20 ),     /* Type Offset=32 */\r
+\r
+       /* Return value */\r
+\r
+/* 1182 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1184 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1186 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Procedure GetComAutomationObject */\r
+\r
+/* 1188 */     0x33,           /* FC_AUTO_HANDLE */\r
+                       0x6c,           /* Old Flags:  object, Oi2 */\r
+/* 1190 */     NdrFcLong( 0x0 ),       /* 0 */\r
+/* 1194 */     NdrFcShort( 0xe ),      /* 14 */\r
+/* 1196 */     NdrFcShort( 0x14 ),     /* x86 Stack size/offset = 20 */\r
+/* 1198 */     NdrFcShort( 0x8 ),      /* 8 */\r
+/* 1200 */     NdrFcShort( 0x8 ),      /* 8 */\r
+/* 1202 */     0x47,           /* Oi2 Flags:  srv must size, clt must size, has return, has ext, */\r
+                       0x4,            /* 4 */\r
+/* 1204 */     0x8,            /* 8 */\r
+                       0x5,            /* Ext Flags:  new corr desc, srv corr check, */\r
+/* 1206 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1208 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1210 */     NdrFcShort( 0x0 ),      /* 0 */\r
+\r
+       /* Parameter bstrProgId */\r
+\r
+/* 1212 */     NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */\r
+/* 1214 */     NdrFcShort( 0x4 ),      /* x86 Stack size/offset = 4 */\r
+/* 1216 */     NdrFcShort( 0x2e ),     /* Type Offset=46 */\r
+\r
+       /* Parameter dwFlags */\r
+\r
+/* 1218 */     NdrFcShort( 0x48 ),     /* Flags:  in, base type, */\r
+/* 1220 */     NdrFcShort( 0x8 ),      /* x86 Stack size/offset = 8 */\r
+/* 1222 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+       /* Parameter ppDisp */\r
+\r
+/* 1224 */     NdrFcShort( 0x13 ),     /* Flags:  must size, must free, out, */\r
+/* 1226 */     NdrFcShort( 0xc ),      /* x86 Stack size/offset = 12 */\r
+/* 1228 */     NdrFcShort( 0x3c ),     /* Type Offset=60 */\r
+\r
+       /* Return value */\r
+\r
+/* 1230 */     NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */\r
+/* 1232 */     NdrFcShort( 0x10 ),     /* x86 Stack size/offset = 16 */\r
+/* 1234 */     0x8,            /* FC_LONG */\r
+                       0x0,            /* 0 */\r
+\r
+                       0x0\r
+        }\r
+    };\r
+\r
+static const xcpctrl_MIDL_TYPE_FORMAT_STRING xcpctrl__MIDL_TypeFormatString =\r
+    {\r
+        0,\r
+        {\r
+                       NdrFcShort( 0x0 ),      /* 0 */\r
+/*  2 */       \r
+                       0x11, 0x4,      /* FC_RP [alloced_on_stack] */\r
+/*  4 */       NdrFcShort( 0x1c ),     /* Offset= 28 (32) */\r
+/*  6 */       \r
+                       0x13, 0x0,      /* FC_OP */\r
+/*  8 */       NdrFcShort( 0xe ),      /* Offset= 14 (22) */\r
+/* 10 */       \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x1,            /* 1 */\r
+/* 12 */       NdrFcShort( 0x2 ),      /* 2 */\r
+/* 14 */       0x9,            /* Corr desc: FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 16 */       NdrFcShort( 0xfffc ),   /* -4 */\r
+/* 18 */       NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 20 */       0x6,            /* FC_SHORT */\r
+                       0x5b,           /* FC_END */\r
+/* 22 */       \r
+                       0x17,           /* FC_CSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 24 */       NdrFcShort( 0x8 ),      /* 8 */\r
+/* 26 */       NdrFcShort( 0xfff0 ),   /* Offset= -16 (10) */\r
+/* 28 */       0x8,            /* FC_LONG */\r
+                       0x8,            /* FC_LONG */\r
+/* 30 */       0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 32 */       0xb4,           /* FC_USER_MARSHAL */\r
+                       0x83,           /* 131 */\r
+/* 34 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 36 */       NdrFcShort( 0x4 ),      /* 4 */\r
+/* 38 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 40 */       NdrFcShort( 0xffde ),   /* Offset= -34 (6) */\r
+/* 42 */       \r
+                       0x12, 0x0,      /* FC_UP */\r
+/* 44 */       NdrFcShort( 0xffea ),   /* Offset= -22 (22) */\r
+/* 46 */       0xb4,           /* FC_USER_MARSHAL */\r
+                       0x83,           /* 131 */\r
+/* 48 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 50 */       NdrFcShort( 0x4 ),      /* 4 */\r
+/* 52 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 54 */       NdrFcShort( 0xfff4 ),   /* Offset= -12 (42) */\r
+/* 56 */       \r
+                       0x11, 0xc,      /* FC_RP [alloced_on_stack] [simple_pointer] */\r
+/* 58 */       0x6,            /* FC_SHORT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 60 */       \r
+                       0x11, 0x10,     /* FC_RP [pointer_deref] */\r
+/* 62 */       NdrFcShort( 0x2 ),      /* Offset= 2 (64) */\r
+/* 64 */       \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 66 */       NdrFcLong( 0x20400 ),   /* 132096 */\r
+/* 70 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 72 */       NdrFcShort( 0x0 ),      /* 0 */\r
+/* 74 */       0xc0,           /* 192 */\r
+                       0x0,            /* 0 */\r
+/* 76 */       0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 78 */       0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 80 */       0x0,            /* 0 */\r
+                       0x46,           /* 70 */\r
+/* 82 */       \r
+                       0x11, 0x4,      /* FC_RP [alloced_on_stack] */\r
+/* 84 */       NdrFcShort( 0x3d4 ),    /* Offset= 980 (1064) */\r
+/* 86 */       \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 88 */       NdrFcShort( 0x3bc ),    /* Offset= 956 (1044) */\r
+/* 90 */       \r
+                       0x2b,           /* FC_NON_ENCAPSULATED_UNION */\r
+                       0x9,            /* FC_ULONG */\r
+/* 92 */       0x7,            /* Corr desc: FC_USHORT */\r
+                       0x0,            /*  */\r
+/* 94 */       NdrFcShort( 0xfff8 ),   /* -8 */\r
+/* 96 */       NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 98 */       NdrFcShort( 0x2 ),      /* Offset= 2 (100) */\r
+/* 100 */      NdrFcShort( 0x10 ),     /* 16 */\r
+/* 102 */      NdrFcShort( 0x2f ),     /* 47 */\r
+/* 104 */      NdrFcLong( 0x14 ),      /* 20 */\r
+/* 108 */      NdrFcShort( 0x800b ),   /* Simple arm type: FC_HYPER */\r
+/* 110 */      NdrFcLong( 0x3 ),       /* 3 */\r
+/* 114 */      NdrFcShort( 0x8008 ),   /* Simple arm type: FC_LONG */\r
+/* 116 */      NdrFcLong( 0x11 ),      /* 17 */\r
+/* 120 */      NdrFcShort( 0x8001 ),   /* Simple arm type: FC_BYTE */\r
+/* 122 */      NdrFcLong( 0x2 ),       /* 2 */\r
+/* 126 */      NdrFcShort( 0x8006 ),   /* Simple arm type: FC_SHORT */\r
+/* 128 */      NdrFcLong( 0x4 ),       /* 4 */\r
+/* 132 */      NdrFcShort( 0x800a ),   /* Simple arm type: FC_FLOAT */\r
+/* 134 */      NdrFcLong( 0x5 ),       /* 5 */\r
+/* 138 */      NdrFcShort( 0x800c ),   /* Simple arm type: FC_DOUBLE */\r
+/* 140 */      NdrFcLong( 0xb ),       /* 11 */\r
+/* 144 */      NdrFcShort( 0x8006 ),   /* Simple arm type: FC_SHORT */\r
+/* 146 */      NdrFcLong( 0xa ),       /* 10 */\r
+/* 150 */      NdrFcShort( 0x8008 ),   /* Simple arm type: FC_LONG */\r
+/* 152 */      NdrFcLong( 0x6 ),       /* 6 */\r
+/* 156 */      NdrFcShort( 0xe8 ),     /* Offset= 232 (388) */\r
+/* 158 */      NdrFcLong( 0x7 ),       /* 7 */\r
+/* 162 */      NdrFcShort( 0x800c ),   /* Simple arm type: FC_DOUBLE */\r
+/* 164 */      NdrFcLong( 0x8 ),       /* 8 */\r
+/* 168 */      NdrFcShort( 0xff5e ),   /* Offset= -162 (6) */\r
+/* 170 */      NdrFcLong( 0xd ),       /* 13 */\r
+/* 174 */      NdrFcShort( 0xdc ),     /* Offset= 220 (394) */\r
+/* 176 */      NdrFcLong( 0x9 ),       /* 9 */\r
+/* 180 */      NdrFcShort( 0xff8c ),   /* Offset= -116 (64) */\r
+/* 182 */      NdrFcLong( 0x2000 ),    /* 8192 */\r
+/* 186 */      NdrFcShort( 0xe2 ),     /* Offset= 226 (412) */\r
+/* 188 */      NdrFcLong( 0x24 ),      /* 36 */\r
+/* 192 */      NdrFcShort( 0x30a ),    /* Offset= 778 (970) */\r
+/* 194 */      NdrFcLong( 0x4024 ),    /* 16420 */\r
+/* 198 */      NdrFcShort( 0x304 ),    /* Offset= 772 (970) */\r
+/* 200 */      NdrFcLong( 0x4011 ),    /* 16401 */\r
+/* 204 */      NdrFcShort( 0x302 ),    /* Offset= 770 (974) */\r
+/* 206 */      NdrFcLong( 0x4002 ),    /* 16386 */\r
+/* 210 */      NdrFcShort( 0x300 ),    /* Offset= 768 (978) */\r
+/* 212 */      NdrFcLong( 0x4003 ),    /* 16387 */\r
+/* 216 */      NdrFcShort( 0x2fe ),    /* Offset= 766 (982) */\r
+/* 218 */      NdrFcLong( 0x4014 ),    /* 16404 */\r
+/* 222 */      NdrFcShort( 0x2fc ),    /* Offset= 764 (986) */\r
+/* 224 */      NdrFcLong( 0x4004 ),    /* 16388 */\r
+/* 228 */      NdrFcShort( 0x2fa ),    /* Offset= 762 (990) */\r
+/* 230 */      NdrFcLong( 0x4005 ),    /* 16389 */\r
+/* 234 */      NdrFcShort( 0x2f8 ),    /* Offset= 760 (994) */\r
+/* 236 */      NdrFcLong( 0x400b ),    /* 16395 */\r
+/* 240 */      NdrFcShort( 0x2e2 ),    /* Offset= 738 (978) */\r
+/* 242 */      NdrFcLong( 0x400a ),    /* 16394 */\r
+/* 246 */      NdrFcShort( 0x2e0 ),    /* Offset= 736 (982) */\r
+/* 248 */      NdrFcLong( 0x4006 ),    /* 16390 */\r
+/* 252 */      NdrFcShort( 0x2ea ),    /* Offset= 746 (998) */\r
+/* 254 */      NdrFcLong( 0x4007 ),    /* 16391 */\r
+/* 258 */      NdrFcShort( 0x2e0 ),    /* Offset= 736 (994) */\r
+/* 260 */      NdrFcLong( 0x4008 ),    /* 16392 */\r
+/* 264 */      NdrFcShort( 0x2e2 ),    /* Offset= 738 (1002) */\r
+/* 266 */      NdrFcLong( 0x400d ),    /* 16397 */\r
+/* 270 */      NdrFcShort( 0x2e0 ),    /* Offset= 736 (1006) */\r
+/* 272 */      NdrFcLong( 0x4009 ),    /* 16393 */\r
+/* 276 */      NdrFcShort( 0x2de ),    /* Offset= 734 (1010) */\r
+/* 278 */      NdrFcLong( 0x6000 ),    /* 24576 */\r
+/* 282 */      NdrFcShort( 0x2dc ),    /* Offset= 732 (1014) */\r
+/* 284 */      NdrFcLong( 0x400c ),    /* 16396 */\r
+/* 288 */      NdrFcShort( 0x2da ),    /* Offset= 730 (1018) */\r
+/* 290 */      NdrFcLong( 0x10 ),      /* 16 */\r
+/* 294 */      NdrFcShort( 0x8002 ),   /* Simple arm type: FC_CHAR */\r
+/* 296 */      NdrFcLong( 0x12 ),      /* 18 */\r
+/* 300 */      NdrFcShort( 0x8006 ),   /* Simple arm type: FC_SHORT */\r
+/* 302 */      NdrFcLong( 0x13 ),      /* 19 */\r
+/* 306 */      NdrFcShort( 0x8008 ),   /* Simple arm type: FC_LONG */\r
+/* 308 */      NdrFcLong( 0x15 ),      /* 21 */\r
+/* 312 */      NdrFcShort( 0x800b ),   /* Simple arm type: FC_HYPER */\r
+/* 314 */      NdrFcLong( 0x16 ),      /* 22 */\r
+/* 318 */      NdrFcShort( 0x8008 ),   /* Simple arm type: FC_LONG */\r
+/* 320 */      NdrFcLong( 0x17 ),      /* 23 */\r
+/* 324 */      NdrFcShort( 0x8008 ),   /* Simple arm type: FC_LONG */\r
+/* 326 */      NdrFcLong( 0xe ),       /* 14 */\r
+/* 330 */      NdrFcShort( 0x2b8 ),    /* Offset= 696 (1026) */\r
+/* 332 */      NdrFcLong( 0x400e ),    /* 16398 */\r
+/* 336 */      NdrFcShort( 0x2bc ),    /* Offset= 700 (1036) */\r
+/* 338 */      NdrFcLong( 0x4010 ),    /* 16400 */\r
+/* 342 */      NdrFcShort( 0x2ba ),    /* Offset= 698 (1040) */\r
+/* 344 */      NdrFcLong( 0x4012 ),    /* 16402 */\r
+/* 348 */      NdrFcShort( 0x276 ),    /* Offset= 630 (978) */\r
+/* 350 */      NdrFcLong( 0x4013 ),    /* 16403 */\r
+/* 354 */      NdrFcShort( 0x274 ),    /* Offset= 628 (982) */\r
+/* 356 */      NdrFcLong( 0x4015 ),    /* 16405 */\r
+/* 360 */      NdrFcShort( 0x272 ),    /* Offset= 626 (986) */\r
+/* 362 */      NdrFcLong( 0x4016 ),    /* 16406 */\r
+/* 366 */      NdrFcShort( 0x268 ),    /* Offset= 616 (982) */\r
+/* 368 */      NdrFcLong( 0x4017 ),    /* 16407 */\r
+/* 372 */      NdrFcShort( 0x262 ),    /* Offset= 610 (982) */\r
+/* 374 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 378 */      NdrFcShort( 0x0 ),      /* Offset= 0 (378) */\r
+/* 380 */      NdrFcLong( 0x1 ),       /* 1 */\r
+/* 384 */      NdrFcShort( 0x0 ),      /* Offset= 0 (384) */\r
+/* 386 */      NdrFcShort( 0xffff ),   /* Offset= -1 (385) */\r
+/* 388 */      \r
+                       0x15,           /* FC_STRUCT */\r
+                       0x7,            /* 7 */\r
+/* 390 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 392 */      0xb,            /* FC_HYPER */\r
+                       0x5b,           /* FC_END */\r
+/* 394 */      \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 396 */      NdrFcLong( 0x0 ),       /* 0 */\r
+/* 400 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 402 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 404 */      0xc0,           /* 192 */\r
+                       0x0,            /* 0 */\r
+/* 406 */      0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 408 */      0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 410 */      0x0,            /* 0 */\r
+                       0x46,           /* 70 */\r
+/* 412 */      \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 414 */      NdrFcShort( 0x2 ),      /* Offset= 2 (416) */\r
+/* 416 */      \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 418 */      NdrFcShort( 0x216 ),    /* Offset= 534 (952) */\r
+/* 420 */      \r
+                       0x2a,           /* FC_ENCAPSULATED_UNION */\r
+                       0x49,           /* 73 */\r
+/* 422 */      NdrFcShort( 0x18 ),     /* 24 */\r
+/* 424 */      NdrFcShort( 0xa ),      /* 10 */\r
+/* 426 */      NdrFcLong( 0x8 ),       /* 8 */\r
+/* 430 */      NdrFcShort( 0x5a ),     /* Offset= 90 (520) */\r
+/* 432 */      NdrFcLong( 0xd ),       /* 13 */\r
+/* 436 */      NdrFcShort( 0x7e ),     /* Offset= 126 (562) */\r
+/* 438 */      NdrFcLong( 0x9 ),       /* 9 */\r
+/* 442 */      NdrFcShort( 0x9e ),     /* Offset= 158 (600) */\r
+/* 444 */      NdrFcLong( 0xc ),       /* 12 */\r
+/* 448 */      NdrFcShort( 0xc8 ),     /* Offset= 200 (648) */\r
+/* 450 */      NdrFcLong( 0x24 ),      /* 36 */\r
+/* 454 */      NdrFcShort( 0x124 ),    /* Offset= 292 (746) */\r
+/* 456 */      NdrFcLong( 0x800d ),    /* 32781 */\r
+/* 460 */      NdrFcShort( 0x140 ),    /* Offset= 320 (780) */\r
+/* 462 */      NdrFcLong( 0x10 ),      /* 16 */\r
+/* 466 */      NdrFcShort( 0x15a ),    /* Offset= 346 (812) */\r
+/* 468 */      NdrFcLong( 0x2 ),       /* 2 */\r
+/* 472 */      NdrFcShort( 0x174 ),    /* Offset= 372 (844) */\r
+/* 474 */      NdrFcLong( 0x3 ),       /* 3 */\r
+/* 478 */      NdrFcShort( 0x18e ),    /* Offset= 398 (876) */\r
+/* 480 */      NdrFcLong( 0x14 ),      /* 20 */\r
+/* 484 */      NdrFcShort( 0x1a8 ),    /* Offset= 424 (908) */\r
+/* 486 */      NdrFcShort( 0xffff ),   /* Offset= -1 (485) */\r
+/* 488 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x3,            /* 3 */\r
+/* 490 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 492 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 494 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 496 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 498 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 500 */      \r
+                       0x48,           /* FC_VARIABLE_REPEAT */\r
+                       0x49,           /* FC_FIXED_OFFSET */\r
+/* 502 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 504 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 506 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 508 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 510 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 512 */      0x13, 0x0,      /* FC_OP */\r
+/* 514 */      NdrFcShort( 0xfe14 ),   /* Offset= -492 (22) */\r
+/* 516 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 518 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 520 */      \r
+                       0x16,           /* FC_PSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 522 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 524 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 526 */      \r
+                       0x46,           /* FC_NO_REPEAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 528 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 530 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 532 */      0x11, 0x0,      /* FC_RP */\r
+/* 534 */      NdrFcShort( 0xffd2 ),   /* Offset= -46 (488) */\r
+/* 536 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 538 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 540 */      \r
+                       0x21,           /* FC_BOGUS_ARRAY */\r
+                       0x3,            /* 3 */\r
+/* 542 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 544 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 546 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 548 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 550 */      NdrFcLong( 0xffffffff ),        /* -1 */\r
+/* 554 */      NdrFcShort( 0x0 ),      /* Corr flags:  */\r
+/* 556 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 558 */      NdrFcShort( 0xff5c ),   /* Offset= -164 (394) */\r
+/* 560 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 562 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 564 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 566 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 568 */      NdrFcShort( 0x6 ),      /* Offset= 6 (574) */\r
+/* 570 */      0x8,            /* FC_LONG */\r
+                       0x36,           /* FC_POINTER */\r
+/* 572 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 574 */      \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 576 */      NdrFcShort( 0xffdc ),   /* Offset= -36 (540) */\r
+/* 578 */      \r
+                       0x21,           /* FC_BOGUS_ARRAY */\r
+                       0x3,            /* 3 */\r
+/* 580 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 582 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 584 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 586 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 588 */      NdrFcLong( 0xffffffff ),        /* -1 */\r
+/* 592 */      NdrFcShort( 0x0 ),      /* Corr flags:  */\r
+/* 594 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 596 */      NdrFcShort( 0xfdec ),   /* Offset= -532 (64) */\r
+/* 598 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 600 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 602 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 604 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 606 */      NdrFcShort( 0x6 ),      /* Offset= 6 (612) */\r
+/* 608 */      0x8,            /* FC_LONG */\r
+                       0x36,           /* FC_POINTER */\r
+/* 610 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 612 */      \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 614 */      NdrFcShort( 0xffdc ),   /* Offset= -36 (578) */\r
+/* 616 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x3,            /* 3 */\r
+/* 618 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 620 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 622 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 624 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 626 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 628 */      \r
+                       0x48,           /* FC_VARIABLE_REPEAT */\r
+                       0x49,           /* FC_FIXED_OFFSET */\r
+/* 630 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 632 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 634 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 636 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 638 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 640 */      0x13, 0x0,      /* FC_OP */\r
+/* 642 */      NdrFcShort( 0x192 ),    /* Offset= 402 (1044) */\r
+/* 644 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 646 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 648 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 650 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 652 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 654 */      NdrFcShort( 0x6 ),      /* Offset= 6 (660) */\r
+/* 656 */      0x8,            /* FC_LONG */\r
+                       0x36,           /* FC_POINTER */\r
+/* 658 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 660 */      \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 662 */      NdrFcShort( 0xffd2 ),   /* Offset= -46 (616) */\r
+/* 664 */      \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 666 */      NdrFcLong( 0x2f ),      /* 47 */\r
+/* 670 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 672 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 674 */      0xc0,           /* 192 */\r
+                       0x0,            /* 0 */\r
+/* 676 */      0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 678 */      0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 680 */      0x0,            /* 0 */\r
+                       0x46,           /* 70 */\r
+/* 682 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x0,            /* 0 */\r
+/* 684 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 686 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 688 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 690 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 692 */      0x1,            /* FC_BYTE */\r
+                       0x5b,           /* FC_END */\r
+/* 694 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 696 */      NdrFcShort( 0x10 ),     /* 16 */\r
+/* 698 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 700 */      NdrFcShort( 0xa ),      /* Offset= 10 (710) */\r
+/* 702 */      0x8,            /* FC_LONG */\r
+                       0x8,            /* FC_LONG */\r
+/* 704 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 706 */      NdrFcShort( 0xffd6 ),   /* Offset= -42 (664) */\r
+/* 708 */      0x36,           /* FC_POINTER */\r
+                       0x5b,           /* FC_END */\r
+/* 710 */      \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 712 */      NdrFcShort( 0xffe2 ),   /* Offset= -30 (682) */\r
+/* 714 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x3,            /* 3 */\r
+/* 716 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 718 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 720 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 722 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 724 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 726 */      \r
+                       0x48,           /* FC_VARIABLE_REPEAT */\r
+                       0x49,           /* FC_FIXED_OFFSET */\r
+/* 728 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 730 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 732 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 734 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 736 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 738 */      0x13, 0x0,      /* FC_OP */\r
+/* 740 */      NdrFcShort( 0xffd2 ),   /* Offset= -46 (694) */\r
+/* 742 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 744 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 746 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 748 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 750 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 752 */      NdrFcShort( 0x6 ),      /* Offset= 6 (758) */\r
+/* 754 */      0x8,            /* FC_LONG */\r
+                       0x36,           /* FC_POINTER */\r
+/* 756 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 758 */      \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 760 */      NdrFcShort( 0xffd2 ),   /* Offset= -46 (714) */\r
+/* 762 */      \r
+                       0x1d,           /* FC_SMFARRAY */\r
+                       0x0,            /* 0 */\r
+/* 764 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 766 */      0x1,            /* FC_BYTE */\r
+                       0x5b,           /* FC_END */\r
+/* 768 */      \r
+                       0x15,           /* FC_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 770 */      NdrFcShort( 0x10 ),     /* 16 */\r
+/* 772 */      0x8,            /* FC_LONG */\r
+                       0x6,            /* FC_SHORT */\r
+/* 774 */      0x6,            /* FC_SHORT */\r
+                       0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+/* 776 */      0x0,            /* 0 */\r
+                       NdrFcShort( 0xfff1 ),   /* Offset= -15 (762) */\r
+                       0x5b,           /* FC_END */\r
+/* 780 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 782 */      NdrFcShort( 0x18 ),     /* 24 */\r
+/* 784 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 786 */      NdrFcShort( 0xa ),      /* Offset= 10 (796) */\r
+/* 788 */      0x8,            /* FC_LONG */\r
+                       0x36,           /* FC_POINTER */\r
+/* 790 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 792 */      NdrFcShort( 0xffe8 ),   /* Offset= -24 (768) */\r
+/* 794 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 796 */      \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 798 */      NdrFcShort( 0xfefe ),   /* Offset= -258 (540) */\r
+/* 800 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x0,            /* 0 */\r
+/* 802 */      NdrFcShort( 0x1 ),      /* 1 */\r
+/* 804 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 806 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 808 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 810 */      0x1,            /* FC_BYTE */\r
+                       0x5b,           /* FC_END */\r
+/* 812 */      \r
+                       0x16,           /* FC_PSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 814 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 816 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 818 */      \r
+                       0x46,           /* FC_NO_REPEAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 820 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 822 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 824 */      0x13, 0x0,      /* FC_OP */\r
+/* 826 */      NdrFcShort( 0xffe6 ),   /* Offset= -26 (800) */\r
+/* 828 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 830 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 832 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x1,            /* 1 */\r
+/* 834 */      NdrFcShort( 0x2 ),      /* 2 */\r
+/* 836 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 838 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 840 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 842 */      0x6,            /* FC_SHORT */\r
+                       0x5b,           /* FC_END */\r
+/* 844 */      \r
+                       0x16,           /* FC_PSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 846 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 848 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 850 */      \r
+                       0x46,           /* FC_NO_REPEAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 852 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 854 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 856 */      0x13, 0x0,      /* FC_OP */\r
+/* 858 */      NdrFcShort( 0xffe6 ),   /* Offset= -26 (832) */\r
+/* 860 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 862 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 864 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x3,            /* 3 */\r
+/* 866 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 868 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 870 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 872 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 874 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 876 */      \r
+                       0x16,           /* FC_PSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 878 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 880 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 882 */      \r
+                       0x46,           /* FC_NO_REPEAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 884 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 886 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 888 */      0x13, 0x0,      /* FC_OP */\r
+/* 890 */      NdrFcShort( 0xffe6 ),   /* Offset= -26 (864) */\r
+/* 892 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 894 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 896 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x7,            /* 7 */\r
+/* 898 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 900 */      0x19,           /* Corr desc:  field pointer, FC_ULONG */\r
+                       0x0,            /*  */\r
+/* 902 */      NdrFcShort( 0x0 ),      /* 0 */\r
+/* 904 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 906 */      0xb,            /* FC_HYPER */\r
+                       0x5b,           /* FC_END */\r
+/* 908 */      \r
+                       0x16,           /* FC_PSTRUCT */\r
+                       0x3,            /* 3 */\r
+/* 910 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 912 */      \r
+                       0x4b,           /* FC_PP */\r
+                       0x5c,           /* FC_PAD */\r
+/* 914 */      \r
+                       0x46,           /* FC_NO_REPEAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 916 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 918 */      NdrFcShort( 0x4 ),      /* 4 */\r
+/* 920 */      0x13, 0x0,      /* FC_OP */\r
+/* 922 */      NdrFcShort( 0xffe6 ),   /* Offset= -26 (896) */\r
+/* 924 */      \r
+                       0x5b,           /* FC_END */\r
+\r
+                       0x8,            /* FC_LONG */\r
+/* 926 */      0x8,            /* FC_LONG */\r
+                       0x5b,           /* FC_END */\r
+/* 928 */      \r
+                       0x15,           /* FC_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 930 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 932 */      0x8,            /* FC_LONG */\r
+                       0x8,            /* FC_LONG */\r
+/* 934 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 936 */      \r
+                       0x1b,           /* FC_CARRAY */\r
+                       0x3,            /* 3 */\r
+/* 938 */      NdrFcShort( 0x8 ),      /* 8 */\r
+/* 940 */      0x7,            /* Corr desc: FC_USHORT */\r
+                       0x0,            /*  */\r
+/* 942 */      NdrFcShort( 0xffd8 ),   /* -40 */\r
+/* 944 */      NdrFcShort( 0x1 ),      /* Corr flags:  early, */\r
+/* 946 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 948 */      NdrFcShort( 0xffec ),   /* Offset= -20 (928) */\r
+/* 950 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 952 */      \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x3,            /* 3 */\r
+/* 954 */      NdrFcShort( 0x28 ),     /* 40 */\r
+/* 956 */      NdrFcShort( 0xffec ),   /* Offset= -20 (936) */\r
+/* 958 */      NdrFcShort( 0x0 ),      /* Offset= 0 (958) */\r
+/* 960 */      0x6,            /* FC_SHORT */\r
+                       0x6,            /* FC_SHORT */\r
+/* 962 */      0x8,            /* FC_LONG */\r
+                       0x8,            /* FC_LONG */\r
+/* 964 */      0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 966 */      NdrFcShort( 0xfdde ),   /* Offset= -546 (420) */\r
+/* 968 */      0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 970 */      \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 972 */      NdrFcShort( 0xfeea ),   /* Offset= -278 (694) */\r
+/* 974 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 976 */      0x1,            /* FC_BYTE */\r
+                       0x5c,           /* FC_PAD */\r
+/* 978 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 980 */      0x6,            /* FC_SHORT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 982 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 984 */      0x8,            /* FC_LONG */\r
+                       0x5c,           /* FC_PAD */\r
+/* 986 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 988 */      0xb,            /* FC_HYPER */\r
+                       0x5c,           /* FC_PAD */\r
+/* 990 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 992 */      0xa,            /* FC_FLOAT */\r
+                       0x5c,           /* FC_PAD */\r
+/* 994 */      \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 996 */      0xc,            /* FC_DOUBLE */\r
+                       0x5c,           /* FC_PAD */\r
+/* 998 */      \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 1000 */     NdrFcShort( 0xfd9c ),   /* Offset= -612 (388) */\r
+/* 1002 */     \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 1004 */     NdrFcShort( 0xfc1a ),   /* Offset= -998 (6) */\r
+/* 1006 */     \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 1008 */     NdrFcShort( 0xfd9a ),   /* Offset= -614 (394) */\r
+/* 1010 */     \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 1012 */     NdrFcShort( 0xfc4c ),   /* Offset= -948 (64) */\r
+/* 1014 */     \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 1016 */     NdrFcShort( 0xfda4 ),   /* Offset= -604 (412) */\r
+/* 1018 */     \r
+                       0x13, 0x10,     /* FC_OP [pointer_deref] */\r
+/* 1020 */     NdrFcShort( 0x2 ),      /* Offset= 2 (1022) */\r
+/* 1022 */     \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 1024 */     NdrFcShort( 0x14 ),     /* Offset= 20 (1044) */\r
+/* 1026 */     \r
+                       0x15,           /* FC_STRUCT */\r
+                       0x7,            /* 7 */\r
+/* 1028 */     NdrFcShort( 0x10 ),     /* 16 */\r
+/* 1030 */     0x6,            /* FC_SHORT */\r
+                       0x1,            /* FC_BYTE */\r
+/* 1032 */     0x1,            /* FC_BYTE */\r
+                       0x8,            /* FC_LONG */\r
+/* 1034 */     0xb,            /* FC_HYPER */\r
+                       0x5b,           /* FC_END */\r
+/* 1036 */     \r
+                       0x13, 0x0,      /* FC_OP */\r
+/* 1038 */     NdrFcShort( 0xfff4 ),   /* Offset= -12 (1026) */\r
+/* 1040 */     \r
+                       0x13, 0x8,      /* FC_OP [simple_pointer] */\r
+/* 1042 */     0x2,            /* FC_CHAR */\r
+                       0x5c,           /* FC_PAD */\r
+/* 1044 */     \r
+                       0x1a,           /* FC_BOGUS_STRUCT */\r
+                       0x7,            /* 7 */\r
+/* 1046 */     NdrFcShort( 0x20 ),     /* 32 */\r
+/* 1048 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1050 */     NdrFcShort( 0x0 ),      /* Offset= 0 (1050) */\r
+/* 1052 */     0x8,            /* FC_LONG */\r
+                       0x8,            /* FC_LONG */\r
+/* 1054 */     0x6,            /* FC_SHORT */\r
+                       0x6,            /* FC_SHORT */\r
+/* 1056 */     0x6,            /* FC_SHORT */\r
+                       0x6,            /* FC_SHORT */\r
+/* 1058 */     0x4c,           /* FC_EMBEDDED_COMPLEX */\r
+                       0x0,            /* 0 */\r
+/* 1060 */     NdrFcShort( 0xfc36 ),   /* Offset= -970 (90) */\r
+/* 1062 */     0x5c,           /* FC_PAD */\r
+                       0x5b,           /* FC_END */\r
+/* 1064 */     0xb4,           /* FC_USER_MARSHAL */\r
+                       0x83,           /* 131 */\r
+/* 1066 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1068 */     NdrFcShort( 0x10 ),     /* 16 */\r
+/* 1070 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1072 */     NdrFcShort( 0xfc26 ),   /* Offset= -986 (86) */\r
+/* 1074 */     \r
+                       0x11, 0x0,      /* FC_RP */\r
+/* 1076 */     NdrFcShort( 0x6 ),      /* Offset= 6 (1082) */\r
+/* 1078 */     \r
+                       0x12, 0x0,      /* FC_UP */\r
+/* 1080 */     NdrFcShort( 0xffdc ),   /* Offset= -36 (1044) */\r
+/* 1082 */     0xb4,           /* FC_USER_MARSHAL */\r
+                       0x83,           /* 131 */\r
+/* 1084 */     NdrFcShort( 0x1 ),      /* 1 */\r
+/* 1086 */     NdrFcShort( 0x10 ),     /* 16 */\r
+/* 1088 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1090 */     NdrFcShort( 0xfff4 ),   /* Offset= -12 (1078) */\r
+/* 1092 */     \r
+                       0x11, 0x10,     /* FC_RP [pointer_deref] */\r
+/* 1094 */     NdrFcShort( 0x2 ),      /* Offset= 2 (1096) */\r
+/* 1096 */     \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 1098 */     NdrFcLong( 0xee38d0f1 ),        /* -298266383 */\r
+/* 1102 */     NdrFcShort( 0x5ae3 ),   /* 23267 */\r
+/* 1104 */     NdrFcShort( 0x408c ),   /* 16524 */\r
+/* 1106 */     0xa6,           /* 166 */\r
+                       0xbf,           /* 191 */\r
+/* 1108 */     0x84,           /* 132 */\r
+                       0x10,           /* 16 */\r
+/* 1110 */     0xe6,           /* 230 */\r
+                       0x45,           /* 69 */\r
+/* 1112 */     0xf3,           /* 243 */\r
+                       0x76,           /* 118 */\r
+/* 1114 */     \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 1116 */     NdrFcLong( 0xc ),       /* 12 */\r
+/* 1120 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1122 */     NdrFcShort( 0x0 ),      /* 0 */\r
+/* 1124 */     0xc0,           /* 192 */\r
+                       0x0,            /* 0 */\r
+/* 1126 */     0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 1128 */     0x0,            /* 0 */\r
+                       0x0,            /* 0 */\r
+/* 1130 */     0x0,            /* 0 */\r
+                       0x46,           /* 70 */\r
+/* 1132 */     \r
+                       0x11, 0xc,      /* FC_RP [alloced_on_stack] [simple_pointer] */\r
+/* 1134 */     0x8,            /* FC_LONG */\r
+                       0x5c,           /* FC_PAD */\r
+/* 1136 */     \r
+                       0x2f,           /* FC_IP */\r
+                       0x5a,           /* FC_CONSTANT_IID */\r
+/* 1138 */     NdrFcLong( 0x2e340632 ),        /* 775161394 */\r
+/* 1142 */     NdrFcShort( 0x5d5a ),   /* 23898 */\r
+/* 1144 */     NdrFcShort( 0x427b ),   /* 17019 */\r
+/* 1146 */     0xac,           /* 172 */\r
+                       0x31,           /* 49 */\r
+/* 1148 */     0x30,           /* 48 */\r
+                       0x3f,           /* 63 */\r
+/* 1150 */     0x6e,           /* 110 */\r
+                       0x32,           /* 50 */\r
+/* 1152 */     0xb9,           /* 185 */\r
+                       0xe8,           /* 232 */\r
+/* 1154 */     \r
+                       0x11, 0x10,     /* FC_RP [pointer_deref] */\r
+/* 1156 */     NdrFcShort( 0xffd6 ),   /* Offset= -42 (1114) */\r
+/* 1158 */     \r
+                       0x11, 0x10,     /* FC_RP [pointer_deref] */\r
+/* 1160 */     NdrFcShort( 0xfd02 ),   /* Offset= -766 (394) */\r
+\r
+                       0x0\r
+        }\r
+    };\r
+\r
+static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ] = \r
+        {\r
+            \r
+            {\r
+            BSTR_UserSize\r
+            ,BSTR_UserMarshal\r
+            ,BSTR_UserUnmarshal\r
+            ,BSTR_UserFree\r
+            },\r
+            {\r
+            VARIANT_UserSize\r
+            ,VARIANT_UserMarshal\r
+            ,VARIANT_UserUnmarshal\r
+            ,VARIANT_UserFree\r
+            }\r
+\r
+        };\r
+\r
+\r
+\r
+/* Object interface: IUnknown, ver. 0.0,\r
+   GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */\r
+\r
+\r
+/* Object interface: IDispatch, ver. 0.0,\r
+   GUID={0x00020400,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */\r
+\r
+\r
+/* Object interface: IXcpObject, ver. 0.0,\r
+   GUID={0xEE38D0F1,0x5AE3,0x408c,{0xA6,0xBF,0x84,0x10,0xE6,0x45,0xF3,0x76}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpObject_FormatStringOffsetTable[] =\r
+    {\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    0\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpObject_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpObject_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpObject_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpObject_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(7) _IXcpObjectProxyVtbl = \r
+{\r
+    0,\r
+    &IID_IXcpObject,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    0 /* IDispatch::GetTypeInfoCount */ ,\r
+    0 /* IDispatch::GetTypeInfo */ ,\r
+    0 /* IDispatch::GetIDsOfNames */ ,\r
+    0 /* IDispatch_Invoke_Proxy */\r
+};\r
+\r
+\r
+static const PRPC_STUB_FUNCTION IXcpObject_table[] =\r
+{\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION\r
+};\r
+\r
+CInterfaceStubVtbl _IXcpObjectStubVtbl =\r
+{\r
+    &IID_IXcpObject,\r
+    &IXcpObject_ServerInfo,\r
+    7,\r
+    &IXcpObject_table[-3],\r
+    CStdStubBuffer_DELEGATING_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControl, ver. 0.0,\r
+   GUID={0x1FB839CC,0x116C,0x4C9B,{0xAE,0x8E,0x3D,0xBB,0x64,0x96,0xE3,0x26}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControl_FormatStringOffsetTable[] =\r
+    {\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    0,\r
+    36,\r
+    72,\r
+    108,\r
+    144,\r
+    180,\r
+    216,\r
+    252,\r
+    288,\r
+    324,\r
+    366,\r
+    408,\r
+    444\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControl_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControl_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControl_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControl_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(20) _IXcpControlProxyVtbl = \r
+{\r
+    &IXcpControl_ProxyInfo,\r
+    &IID_IXcpControl,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    0 /* IDispatch::GetTypeInfoCount */ ,\r
+    0 /* IDispatch::GetTypeInfo */ ,\r
+    0 /* IDispatch::GetIDsOfNames */ ,\r
+    0 /* IDispatch_Invoke_Proxy */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Source */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_Source */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_IsLoaded */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Content */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Settings */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_OnLoad */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_OnLoad */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_OnError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_OnError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::CreateObject */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::IsVersionSupported */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_InitParams */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_InitParams */\r
+};\r
+\r
+\r
+static const PRPC_STUB_FUNCTION IXcpControl_table[] =\r
+{\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2\r
+};\r
+\r
+CInterfaceStubVtbl _IXcpControlStubVtbl =\r
+{\r
+    &IID_IXcpControl,\r
+    &IXcpControl_ServerInfo,\r
+    20,\r
+    &IXcpControl_table[-3],\r
+    CStdStubBuffer_DELEGATING_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControl2, ver. 0.0,\r
+   GUID={0x1c3294f9,0x891f,0x49b1,{0xbb,0xae,0x49,0x2a,0x68,0xba,0x10,0xcc}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControl2_FormatStringOffsetTable[] =\r
+    {\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    (unsigned short) -1,\r
+    0,\r
+    36,\r
+    72,\r
+    108,\r
+    144,\r
+    180,\r
+    216,\r
+    252,\r
+    288,\r
+    324,\r
+    366,\r
+    408,\r
+    444,\r
+    480,\r
+    510,\r
+    546,\r
+    582,\r
+    618,\r
+    654,\r
+    690\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControl2_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControl2_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControl2_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControl2_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(27) _IXcpControl2ProxyVtbl = \r
+{\r
+    &IXcpControl2_ProxyInfo,\r
+    &IID_IXcpControl2,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    0 /* IDispatch::GetTypeInfoCount */ ,\r
+    0 /* IDispatch::GetTypeInfo */ ,\r
+    0 /* IDispatch::GetIDsOfNames */ ,\r
+    0 /* IDispatch_Invoke_Proxy */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Source */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_Source */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_IsLoaded */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Content */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_Settings */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_OnLoad */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_OnLoad */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_OnError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_OnError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::CreateObject */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::IsVersionSupported */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::get_InitParams */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl::put_InitParams */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::LoadRuntime */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::get_SplashScreenSource */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::put_SplashScreenSource */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::get_OnSourceDownloadComplete */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::put_OnSourceDownloadComplete */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::get_OnSourceDownloadProgressChanged */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControl2::put_OnSourceDownloadProgressChanged */\r
+};\r
+\r
+\r
+static const PRPC_STUB_FUNCTION IXcpControl2_table[] =\r
+{\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    STUB_FORWARDING_FUNCTION,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2,\r
+    NdrStubCall2\r
+};\r
+\r
+CInterfaceStubVtbl _IXcpControl2StubVtbl =\r
+{\r
+    &IID_IXcpControl2,\r
+    &IXcpControl2_ServerInfo,\r
+    27,\r
+    &IXcpControl2_table[-3],\r
+    CStdStubBuffer_DELEGATING_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControlDownloadCallback, ver. 0.0,\r
+   GUID={0x2E340632,0x5D5A,0x427b,{0xAC,0x31,0x30,0x3F,0x6E,0x32,0xB9,0xE8}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControlDownloadCallback_FormatStringOffsetTable[] =\r
+    {\r
+    726\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControlDownloadCallback_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlDownloadCallback_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControlDownloadCallback_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlDownloadCallback_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(4) _IXcpControlDownloadCallbackProxyVtbl = \r
+{\r
+    &IXcpControlDownloadCallback_ProxyInfo,\r
+    &IID_IXcpControlDownloadCallback,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlDownloadCallback::OnUrlDownloaded */\r
+};\r
+\r
+const CInterfaceStubVtbl _IXcpControlDownloadCallbackStubVtbl =\r
+{\r
+    &IID_IXcpControlDownloadCallback,\r
+    &IXcpControlDownloadCallback_ServerInfo,\r
+    4,\r
+    0, /* pure interpreted */\r
+    CStdStubBuffer_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControlHost, ver. 0.0,\r
+   GUID={0x1B36028E,0xB491,0x4bb2,{0x85,0x84,0x8A,0x9E,0x0A,0x67,0x7D,0x6E}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControlHost_FormatStringOffsetTable[] =\r
+    {\r
+    768,\r
+    804,\r
+    834,\r
+    888,\r
+    0,\r
+    942,\r
+    984\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControlHost_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControlHost_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(10) _IXcpControlHostProxyVtbl = \r
+{\r
+    &IXcpControlHost_ProxyInfo,\r
+    &IID_IXcpControlHost,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetHostOptions */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyLoaded */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::InvokeHandler */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetBaseUrl */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetNamedSource */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::DownloadUrl */\r
+};\r
+\r
+const CInterfaceStubVtbl _IXcpControlHostStubVtbl =\r
+{\r
+    &IID_IXcpControlHost,\r
+    &IXcpControlHost_ServerInfo,\r
+    10,\r
+    0, /* pure interpreted */\r
+    CStdStubBuffer_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControlHost2, ver. 0.0,\r
+   GUID={0xfb3ed7c4,0x5797,0x4b44,{0x86,0x95,0x0c,0x51,0x2e,0xa2,0x7d,0x8f}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControlHost2_FormatStringOffsetTable[] =\r
+    {\r
+    768,\r
+    804,\r
+    834,\r
+    888,\r
+    0,\r
+    942,\r
+    984,\r
+    1032,\r
+    1068\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControlHost2_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost2_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControlHost2_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost2_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(12) _IXcpControlHost2ProxyVtbl = \r
+{\r
+    &IXcpControlHost2_ProxyInfo,\r
+    &IID_IXcpControlHost2,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetHostOptions */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyLoaded */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::InvokeHandler */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetBaseUrl */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetNamedSource */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::DownloadUrl */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost2::GetCustomAppDomain */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost2::GetControlVersion */\r
+};\r
+\r
+const CInterfaceStubVtbl _IXcpControlHost2StubVtbl =\r
+{\r
+    &IID_IXcpControlHost2,\r
+    &IXcpControlHost2_ServerInfo,\r
+    12,\r
+    0, /* pure interpreted */\r
+    CStdStubBuffer_METHODS\r
+};\r
+\r
+\r
+/* Object interface: IXcpControlHost3, ver. 0.0,\r
+   GUID={0x9fb2ce5f,0x06ff,0x4058,{0xbe,0xfa,0xdd,0xfa,0xb5,0x96,0xb3,0xd5}} */\r
+\r
+#pragma code_seg(".orpc")\r
+static const unsigned short IXcpControlHost3_FormatStringOffsetTable[] =\r
+    {\r
+    768,\r
+    804,\r
+    834,\r
+    888,\r
+    0,\r
+    942,\r
+    984,\r
+    1032,\r
+    1068,\r
+    1110,\r
+    1152,\r
+    1188\r
+    };\r
+\r
+static const MIDL_STUBLESS_PROXY_INFO IXcpControlHost3_ProxyInfo =\r
+    {\r
+    &Object_StubDesc,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost3_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0\r
+    };\r
+\r
+\r
+static const MIDL_SERVER_INFO IXcpControlHost3_ServerInfo = \r
+    {\r
+    &Object_StubDesc,\r
+    0,\r
+    xcpctrl__MIDL_ProcFormatString.Format,\r
+    &IXcpControlHost3_FormatStringOffsetTable[-3],\r
+    0,\r
+    0,\r
+    0,\r
+    0};\r
+CINTERFACE_PROXY_VTABLE(15) _IXcpControlHost3ProxyVtbl = \r
+{\r
+    &IXcpControlHost3_ProxyInfo,\r
+    &IID_IXcpControlHost3,\r
+    IUnknown_QueryInterface_Proxy,\r
+    IUnknown_AddRef_Proxy,\r
+    IUnknown_Release_Proxy ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetHostOptions */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyLoaded */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::NotifyError */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::InvokeHandler */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetBaseUrl */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::GetNamedSource */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost::DownloadUrl */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost2::GetCustomAppDomain */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost2::GetControlVersion */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost3::GetDefaultThemeXaml */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost3::GetDefaultPortableUserInterfaceFontInfo */ ,\r
+    (void *) (INT_PTR) -1 /* IXcpControlHost3::GetComAutomationObject */\r
+};\r
+\r
+const CInterfaceStubVtbl _IXcpControlHost3StubVtbl =\r
+{\r
+    &IID_IXcpControlHost3,\r
+    &IXcpControlHost3_ServerInfo,\r
+    15,\r
+    0, /* pure interpreted */\r
+    CStdStubBuffer_METHODS\r
+};\r
+\r
+static const MIDL_STUB_DESC Object_StubDesc = \r
+    {\r
+    0,\r
+    NdrOleAllocate,\r
+    NdrOleFree,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    xcpctrl__MIDL_TypeFormatString.Format,\r
+    1, /* -error bounds_check flag */\r
+    0x50002, /* Ndr library version */\r
+    0,\r
+    0x700022b, /* MIDL Version 7.0.555 */\r
+    0,\r
+    UserMarshalRoutines,\r
+    0,  /* notify & notify_flag routine table */\r
+    0x1, /* MIDL flag */\r
+    0, /* cs routines */\r
+    0,   /* proxy/server info */\r
+    0\r
+    };\r
+\r
+const CInterfaceProxyVtbl * const _xcpctrl_ProxyVtblList[] = \r
+{\r
+    ( CInterfaceProxyVtbl *) &_IXcpControlDownloadCallbackProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpControlHost3ProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpControlHostProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpControlHost2ProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpControlProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpObjectProxyVtbl,\r
+    ( CInterfaceProxyVtbl *) &_IXcpControl2ProxyVtbl,\r
+    0\r
+};\r
+\r
+const CInterfaceStubVtbl * const _xcpctrl_StubVtblList[] = \r
+{\r
+    ( CInterfaceStubVtbl *) &_IXcpControlDownloadCallbackStubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpControlHost3StubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpControlHostStubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpControlHost2StubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpControlStubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpObjectStubVtbl,\r
+    ( CInterfaceStubVtbl *) &_IXcpControl2StubVtbl,\r
+    0\r
+};\r
+\r
+PCInterfaceName const _xcpctrl_InterfaceNamesList[] = \r
+{\r
+    "IXcpControlDownloadCallback",\r
+    "IXcpControlHost3",\r
+    "IXcpControlHost",\r
+    "IXcpControlHost2",\r
+    "IXcpControl",\r
+    "IXcpObject",\r
+    "IXcpControl2",\r
+    0\r
+};\r
+\r
+const IID *  const _xcpctrl_BaseIIDList[] = \r
+{\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    &IID_IDispatch,\r
+    &IID_IDispatch,\r
+    &IID_IDispatch,\r
+    0\r
+};\r
+\r
+\r
+#define _xcpctrl_CHECK_IID(n)  IID_GENERIC_CHECK_IID( _xcpctrl, pIID, n)\r
+\r
+int __stdcall _xcpctrl_IID_Lookup( const IID * pIID, int * pIndex )\r
+{\r
+    IID_BS_LOOKUP_SETUP\r
+\r
+    IID_BS_LOOKUP_INITIAL_TEST( _xcpctrl, 7, 4 )\r
+    IID_BS_LOOKUP_NEXT_TEST( _xcpctrl, 2 )\r
+    IID_BS_LOOKUP_NEXT_TEST( _xcpctrl, 1 )\r
+    IID_BS_LOOKUP_RETURN_RESULT( _xcpctrl, 7, *pIndex )\r
+    \r
+}\r
+\r
+const ExtendedProxyFileInfo xcpctrl_ProxyFileInfo = \r
+{\r
+    (PCInterfaceProxyVtblList *) & _xcpctrl_ProxyVtblList,\r
+    (PCInterfaceStubVtblList *) & _xcpctrl_StubVtblList,\r
+    (const PCInterfaceName * ) & _xcpctrl_InterfaceNamesList,\r
+    (const IID ** ) & _xcpctrl_BaseIIDList,\r
+    & _xcpctrl_IID_Lookup, \r
+    7,\r
+    2,\r
+    0, /* table of [async_uuid] interfaces */\r
+    0, /* Filler1 */\r
+    0, /* Filler2 */\r
+    0  /* Filler3 */\r
+};\r
+#pragma optimize("", on )\r
+#if _MSC_VER >= 1200\r
+#pragma warning(pop)\r
+#endif\r
+\r
+\r
+#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/\r
+\r
diff --git a/modules/silverlight/producer/silverlight_producer.cpp b/modules/silverlight/producer/silverlight_producer.cpp
new file mode 100644 (file)
index 0000000..9e86718
--- /dev/null
@@ -0,0 +1,175 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
\r
+#include "../stdafx.h"\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#pragma warning (disable : 4146)\r
+#endif\r
+\r
+#include "silverlight_producer.h"\r
+\r
+#include "../interop/XcpControlHost.h"\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <core/mixer/write_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/env.h>\r
+\r
+#include <boost/filesystem.hpp>\r
+\r
+#include <SFML/Graphics.hpp>\r
+\r
+namespace caspar {\r
+               \r
+class silverlight_renderer\r
+{\r
+       struct co_init\r
+       {\r
+               co_init(){CoInitialize(nullptr);}\r
+               ~co_init(){CoUninitialize();}\r
+       } co;\r
+       \r
+       int id_;\r
+\r
+       const std::shared_ptr<core::frame_factory> frame_factory_;\r
+       const core::video_format_desc format_desc_;\r
+       \r
+       CComObject<XcpControlHost>* host_;\r
+       tbb::spin_mutex mutex_;\r
+       safe_ptr<core::basic_frame> last_frame_;\r
+\r
+       sf::RenderWindow window_;\r
+                       \r
+       HDC screen_;\r
+       HDC mem_;\r
+       HBITMAP bmp_;\r
+       unsigned char* bmp_data_;\r
+\r
+public:\r
+       silverlight_renderer(const std::shared_ptr<core::frame_factory>& frame_factory) \r
+               : frame_factory_(frame_factory)\r
+               , format_desc_(frame_factory->get_video_format_desc())\r
+               , last_frame_(core::basic_frame::empty())\r
+               , host_(nullptr)\r
+               , id_(rand())\r
+               , window_(sf::VideoMode(format_desc_.width, format_desc_.height, 32), boost::lexical_cast<std::string>(id_), sf::Style::None)\r
+       {\r
+               if(FAILED(CComObject<XcpControlHost>::CreateInstance(&host_)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to create XcpControlHost"));\r
+               \r
+               HWND hWnd = ::FindWindow(L"SFML_Window", boost::lexical_cast<std::wstring>(id_).c_str());\r
+               if(FAILED(host_->CreateXcpControl(hWnd)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to Create XcpControl"));\r
+               \r
+               screen_= ::GetDC(hWnd);\r
+               mem_ = ::CreateCompatibleDC(screen_);\r
+                               \r
+               BITMAPINFO info;\r
+               memset(&info, 0, sizeof(BITMAPINFO));\r
+               info.bmiHeader.biBitCount = 32;\r
+               info.bmiHeader.biCompression = BI_RGB;\r
+               info.bmiHeader.biHeight = -static_cast<int>(format_desc_.height);\r
+               info.bmiHeader.biPlanes = 1;\r
+               info.bmiHeader.biSize = sizeof(BITMAPINFO);\r
+               info.bmiHeader.biWidth = format_desc_.width;\r
+\r
+               bmp_ = ::CreateDIBSection(screen_, &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), 0, 0);\r
+               SelectObject(mem_, bmp_);\r
+       }\r
+\r
+       ~silverlight_renderer()\r
+       {               \r
+               DeleteObject(bmp_);\r
+               DeleteDC(mem_);\r
+               DeleteDC(screen_);\r
+\r
+               if(host_)\r
+               {\r
+                       host_->DestroyXcpControl();\r
+                       host_->Release();\r
+               }\r
+       }\r
+                       \r
+       void render()\r
+       {       \r
+               sf::Event Event;\r
+               while (window_.GetEvent(Event)){}\r
+               window_.Display();\r
+                               \r
+               auto frame = frame_factory_->create_frame(this, format_desc_.width, format_desc_.height);\r
+               ::BitBlt(mem_, 0, 0, format_desc_.width, format_desc_.height, screen_, 0, 0, SRCCOPY);          \r
+               std::copy_n(bmp_data_, format_desc_.size, frame->image_data().begin());\r
+\r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               last_frame_ = frame;\r
+       }\r
+               \r
+       safe_ptr<core::basic_frame> get_frame()\r
+       {               \r
+               tbb::spin_mutex::scoped_lock lock(mutex_);\r
+               return last_frame_;\r
+       }\r
+};\r
+\r
+struct silverlight_producer : public core::frame_producer\r
+{                              \r
+       std::unique_ptr<silverlight_renderer> renderer_;\r
+       \r
+       executor executor_;\r
+public:\r
+\r
+       silverlight_producer(const safe_ptr<core::frame_factory>& frame_factory) : executor_(L"silverlight")\r
+       {\r
+               executor_.invoke([=]\r
+               {\r
+                       renderer_.reset(new silverlight_renderer(frame_factory));\r
+               });\r
+       }\r
+               \r
+       virtual safe_ptr<core::basic_frame> receive()\r
+       {\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       renderer_->render();\r
+               });\r
+\r
+               return renderer_->get_frame();\r
+       }\r
+\r
+       std::wstring print() const{ return L"silverlight"; }    \r
+};\r
+\r
+safe_ptr<core::frame_producer> create_silverlight_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+{\r
+       //std::wstring filename = env::template_folder() + L"\\" + params[0] + L".xap";\r
+       //if(!boost::filesystem::exists(filename))\r
+       //      return frame_producer::empty();\r
+       if(params[0] != L"SILVER")\r
+               return core::frame_producer::empty();\r
+\r
+       return make_safe<silverlight_producer>(frame_factory);\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/modules/silverlight/producer/silverlight_producer.h b/modules/silverlight/producer/silverlight_producer.h
new file mode 100644 (file)
index 0000000..7f29d57
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#pragma once\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar {\r
+       \r
+safe_ptr<core::frame_producer> create_silverlight_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
+\r
+}\r
diff --git a/modules/silverlight/silverlight.cpp b/modules/silverlight/silverlight.cpp
new file mode 100644 (file)
index 0000000..a9b9b44
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#include "stdafx.h"\r
+\r
+#include "silverlight.h"\r
+\r
+#include "producer/silverlight_producer.h"\r
+\r
+#include <core/producer/frame_producer.h>\r
+\r
+namespace caspar{\r
+\r
+void init_silverlight()\r
+{\r
+       core::register_producer_factory(create_silverlight_producer);\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/modules/silverlight/silverlight.h b/modules/silverlight/silverlight.h
new file mode 100644 (file)
index 0000000..b2b0b2b
--- /dev/null
@@ -0,0 +1,26 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#pragma once\r
+\r
+namespace caspar {\r
+\r
+void init_silverlight();\r
+\r
+}
\ No newline at end of file
diff --git a/modules/silverlight/silverlight.vcxproj b/modules/silverlight/silverlight.vcxproj
new file mode 100644 (file)
index 0000000..ad9c112
--- /dev/null
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{B964D953-8882-454C-A935-DB711D697E39}</ProjectGuid>\r
+    <RootNamespace>silverlight</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectName>silverlight</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <WholeProgramOptimization>false</WholeProgramOptimization>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+    <UseIntelTBB>true</UseIntelTBB>\r
+    <InstrumentIntelTBB>false</InstrumentIntelTBB>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\;..\..\dependencies\boost\;..\..\dependencies\ffmpeg 0.8\include\;..\..\dependencies\tbb\include\;..\..\dependencies\SFML-1.6\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\..\dependencies\boost\stage\lib\;..\..\dependencies\ffmpeg 0.8\lib\;..\..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectName)</TargetName>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_DEBUG;TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PostBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PostBuildEvent>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="interop\XcpControlHost.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\xcpctrl_i.c">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\xcpctrl_p.c">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\XcpPropertyBag.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\silverlight_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </ClCompile>\r
+    <ClCompile Include="silverlight.cpp">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="interop\XcpControlHost.h" />\r
+    <ClInclude Include="interop\xcpctrl.h" />\r
+    <ClInclude Include="interop\xcpctrl_h.h" />\r
+    <ClInclude Include="interop\XcpPropertyBag.h" />\r
+    <ClInclude Include="producer\silverlight_producer.h" />\r
+    <ClInclude Include="silverlight.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\xcpctrl.idl">\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+    </Midl>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/silverlight/silverlight.vcxproj.filters b/modules/silverlight/silverlight.vcxproj.filters
new file mode 100644 (file)
index 0000000..bd1460a
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="interop">\r
+      <UniqueIdentifier>{4f739737-1661-40dd-afc7-5cc64598f500}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="producer">\r
+      <UniqueIdentifier>{d33ae2d6-7928-46bb-940b-c7c76c601329}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="producer\silverlight_producer.cpp">\r
+      <Filter>producer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\xcpctrl_i.c">\r
+      <Filter>interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\xcpctrl_p.c">\r
+      <Filter>interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\XcpPropertyBag.cpp">\r
+      <Filter>interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="interop\XcpControlHost.cpp">\r
+      <Filter>interop</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="silverlight.cpp" />\r
+    <ClCompile Include="StdAfx.cpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="producer\silverlight_producer.h">\r
+      <Filter>producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\xcpctrl.h">\r
+      <Filter>interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\xcpctrl_h.h">\r
+      <Filter>interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\XcpPropertyBag.h">\r
+      <Filter>interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="interop\XcpControlHost.h">\r
+      <Filter>interop</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="silverlight.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Midl Include="interop\xcpctrl.idl">\r
+      <Filter>interop</Filter>\r
+    </Midl>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/protocol/StdAfx.cpp b/protocol/StdAfx.cpp
new file mode 100644 (file)
index 0000000..78dab68
--- /dev/null
@@ -0,0 +1,22 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "stdafx.h"
\ No newline at end of file
diff --git a/protocol/StdAfx.h b/protocol/StdAfx.h
new file mode 100644 (file)
index 0000000..67b6cca
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#define NOMINMAX\r
+\r
+#if defined(_MSC_VER)\r
+#      ifndef _SCL_SECURE_NO_WARNINGS\r
+#              define _SCL_SECURE_NO_WARNINGS\r
+#      endif\r
+#      ifndef _CRT_SECURE_NO_WARNINGS\r
+#              define _CRT_SECURE_NO_WARNINGS\r
+#      endif\r
+#endif\r
+\r
+#ifdef _DEBUG\r
+#include <crtdbg.h>\r
+#endif\r
+\r
+#include <cstdint>\r
+#include <winsock2.h>\r
+#include <tchar.h>\r
+#include <sstream>\r
+#include <memory>\r
+#include <functional>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <deque>\r
+#include <queue>\r
+#include <string>\r
+#include <math.h>\r
+\r
+#include <boost/assign.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+\r
+#include "../common/utility/string.h"\r
+#include "../common/memory/safe_ptr.h"\r
+//#include "../common/concurrency/executor.h" // Can't include this due to MSVC lambda bug\r
+\r
+#include "../common/log/Log.h"\r
+#include "../common/exception/exceptions.h"\r
+#include "../common/exception/win32_exception.h"\r
+\r
+#include <assert.h>
\ No newline at end of file
diff --git a/protocol/amcp/AMCPCommand.h b/protocol/amcp/AMCPCommand.h
new file mode 100644 (file)
index 0000000..b0200a9
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../util/clientinfo.h"\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/video_channel.h>\r
+#include <core/thumbnail_generator.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+\r
+namespace caspar { namespace protocol {\r
+namespace amcp {\r
+\r
+       enum AMCPCommandScheduling\r
+       {\r
+               Default = 0,\r
+               AddToQueue,\r
+               ImmediatelyAndClear\r
+       };\r
+\r
+       class AMCPCommand\r
+       {\r
+               AMCPCommand(const AMCPCommand&);\r
+               AMCPCommand& operator=(const AMCPCommand&);\r
+       public:\r
+               AMCPCommand();\r
+               virtual ~AMCPCommand() {}\r
+               virtual bool Execute() = 0;\r
+\r
+               virtual bool NeedChannel() = 0;\r
+               virtual AMCPCommandScheduling GetDefaultScheduling() = 0;\r
+               virtual int GetMinimumParameters() = 0;\r
+\r
+               void SendReply();\r
+\r
+               void AddParameter(const std::wstring& param){_parameters.push_back(param);}\r
+\r
+               void SetClientInfo(IO::ClientInfoPtr& s){pClientInfo_ = s;}\r
+               IO::ClientInfoPtr GetClientInfo(){return pClientInfo_;}\r
+\r
+               void SetChannel(const std::shared_ptr<core::video_channel>& pChannel){pChannel_ = pChannel;}\r
+               std::shared_ptr<core::video_channel> GetChannel(){return pChannel_;}\r
+\r
+               void SetChannels(const std::vector<safe_ptr<core::video_channel>>& channels){channels_ = channels;}\r
+               const std::vector<safe_ptr<core::video_channel>>& GetChannels() { return channels_; }\r
+\r
+               void SetThumbGenerator(const std::shared_ptr<core::thumbnail_generator>& thumb_gen) {thumb_gen_ = thumb_gen;}\r
+               std::shared_ptr<core::thumbnail_generator> GetThumbGenerator() { return thumb_gen_; }\r
+\r
+               void SetShutdownServerNow(boost::promise<bool>& shutdown_server_now) {shutdown_server_now_ = &shutdown_server_now;}\r
+               boost::promise<bool>& GetShutdownServerNow() { return *shutdown_server_now_; }\r
+\r
+               void SetChannelIndex(unsigned int channelIndex){channelIndex_ = channelIndex;}\r
+               unsigned int GetChannelIndex(){return channelIndex_;}\r
+\r
+               void SetLayerIntex(int layerIndex){layerIndex_ = layerIndex;}\r
+               int GetLayerIndex(int defaultValue = 0) const{return layerIndex_ != -1 ? layerIndex_ : defaultValue;}\r
+\r
+               virtual void Clear();\r
+\r
+               AMCPCommandScheduling GetScheduling()\r
+               {\r
+                       return scheduling_ == Default ? GetDefaultScheduling() : scheduling_;\r
+               }\r
+\r
+               virtual std::wstring print() const = 0;\r
+\r
+               void SetScheduling(AMCPCommandScheduling s){scheduling_ = s;}\r
+               void SetReplyString(const std::wstring& str){replyString_ = str;}\r
+\r
+       protected:\r
+               std::vector<std::wstring> _parameters;\r
+               std::vector<std::wstring> _parameters2;\r
+\r
+       private:\r
+               unsigned int channelIndex_;\r
+               int layerIndex_;\r
+               IO::ClientInfoPtr pClientInfo_;\r
+               std::shared_ptr<core::video_channel> pChannel_;\r
+               std::vector<safe_ptr<core::video_channel>> channels_;\r
+               std::shared_ptr<core::thumbnail_generator> thumb_gen_;\r
+               boost::promise<bool>* shutdown_server_now_;\r
+               AMCPCommandScheduling scheduling_;\r
+               std::wstring replyString_;\r
+       };\r
+\r
+       typedef std::tr1::shared_ptr<AMCPCommand> AMCPCommandPtr;\r
+\r
+       template<bool TNeedChannel, AMCPCommandScheduling TScheduling, int TMinParameters>\r
+       class AMCPCommandBase : public AMCPCommand\r
+       {\r
+       public:\r
+               virtual bool Execute()\r
+               {\r
+                       _parameters2 = _parameters;\r
+                       for(size_t n = 0; n < _parameters.size(); ++n)\r
+                               _parameters[n] = boost::to_upper_copy(_parameters[n]);\r
+                       return (TNeedChannel && !GetChannel()) || _parameters.size() < TMinParameters ? false : DoExecute();\r
+               }\r
+\r
+               virtual bool NeedChannel(){return TNeedChannel;}                \r
+               virtual AMCPCommandScheduling GetDefaultScheduling(){return TScheduling;}\r
+               virtual int GetMinimumParameters(){return TMinParameters;}\r
+       protected:\r
+               ~AMCPCommandBase(){}\r
+       private:\r
+               virtual bool DoExecute() = 0;\r
+       };      \r
+\r
+}}}\r
diff --git a/protocol/amcp/AMCPCommandQueue.cpp b/protocol/amcp/AMCPCommandQueue.cpp
new file mode 100644 (file)
index 0000000..7a50158
--- /dev/null
@@ -0,0 +1,89 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "..\stdafx.h"\r
+\r
+#include "AMCPCommandQueue.h"\r
+\r
+namespace caspar { namespace protocol { namespace amcp {\r
+       \r
+AMCPCommandQueue::AMCPCommandQueue() \r
+       : executor_(L"AMCPCommandQueue")\r
+{\r
+}\r
+\r
+AMCPCommandQueue::~AMCPCommandQueue() \r
+{\r
+}\r
+\r
+void AMCPCommandQueue::AddCommand(AMCPCommandPtr pCurrentCommand)\r
+{\r
+       if(!pCurrentCommand)\r
+               return;\r
+\r
+       if(pCurrentCommand->GetScheduling() == ImmediatelyAndClear)\r
+               executor_.clear();\r
+\r
+       if(executor_.size() > 64)\r
+       {\r
+               try\r
+               {\r
+                       CASPAR_LOG(error) << "AMCP Command Queue Overflow.";\r
+                       CASPAR_LOG(error) << "Failed to execute command:" << pCurrentCommand->print();\r
+                       pCurrentCommand->SetReplyString(L"500 FAILED\r\n");\r
+                       pCurrentCommand->SendReply();\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
+       \r
+       executor_.begin_invoke([=]\r
+       {\r
+               try\r
+               {\r
+                       try\r
+                       {\r
+                               if(pCurrentCommand->Execute()) \r
+                                       CASPAR_LOG(debug) << "Executed command: " << pCurrentCommand->print();\r
+                               else \r
+                                       CASPAR_LOG(warning) << "Failed to execute command: " << pCurrentCommand->print();\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(error) << "Failed to execute command:" << pCurrentCommand->print();\r
+                               pCurrentCommand->SetReplyString(L"500 FAILED\r\n");\r
+                       }\r
+                               \r
+                       pCurrentCommand->SendReply();\r
+                       \r
+                       CASPAR_LOG(trace) << "Ready for a new command";\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       });\r
+}\r
+\r
+}}}
\ No newline at end of file
diff --git a/protocol/amcp/AMCPCommandQueue.h b/protocol/amcp/AMCPCommandQueue.h
new file mode 100644 (file)
index 0000000..58756c8
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../util/thread.h"\r
+\r
+#include "AMCPCommand.h"\r
+\r
+#include <common/concurrency/executor.h>\r
+\r
+#include <tbb\mutex.h>\r
+\r
+namespace caspar { namespace protocol { namespace amcp {\r
+\r
+class AMCPCommandQueue\r
+{\r
+       AMCPCommandQueue(const AMCPCommandQueue&);\r
+       AMCPCommandQueue& operator=(const AMCPCommandQueue&);\r
+public:\r
+       AMCPCommandQueue();\r
+       ~AMCPCommandQueue();\r
+\r
+       void AddCommand(AMCPCommandPtr pCommand);\r
+\r
+private:\r
+       executor                        executor_;\r
+};\r
+typedef std::tr1::shared_ptr<AMCPCommandQueue> AMCPCommandQueuePtr;\r
+\r
+}}}\r
diff --git a/protocol/amcp/AMCPCommandsImpl.cpp b/protocol/amcp/AMCPCommandsImpl.cpp
new file mode 100644 (file)
index 0000000..19b7ae3
--- /dev/null
@@ -0,0 +1,1854 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
+#endif\r
+\r
+#include "AMCPCommandsImpl.h"\r
+#include "AMCPProtocolStrategy.h"\r
+\r
+#include <common/env.h>\r
+\r
+#include <common/log/log.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/os/windows/current_version.h>\r
+#include <common/os/windows/system_info.h>\r
+#include <common/utility/string.h>\r
+#include <common/utility/utf8conv.h>\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/video_format.h>\r
+#include <core/producer/transition/transition_producer.h>\r
+#include <core/producer/channel/channel_producer.h>\r
+#include <core/producer/frame/frame_transform.h>\r
+#include <core/producer/stage.h>\r
+#include <core/producer/layer.h>\r
+#include <core/mixer/mixer.h>\r
+#include <core/mixer/gpu/ogl_device.h>\r
+#include <core/consumer/output.h>\r
+\r
+#include <modules/bluefish/bluefish.h>\r
+#include <modules/decklink/decklink.h>\r
+#include <modules/ffmpeg/ffmpeg.h>\r
+#include <modules/flash/flash.h>\r
+#include <modules/flash/util/swf.h>\r
+#include <modules/flash/producer/flash_producer.h>\r
+#include <modules/flash/producer/cg_producer.h>\r
+#include <modules/ffmpeg/producer/util/util.h>\r
+#include <modules/image/image.h>\r
+#include <modules/ogl/ogl.h>\r
+\r
+#include <algorithm>\r
+#include <locale>\r
+#include <fstream>\r
+#include <memory>\r
+#include <cctype>\r
+#include <io.h>\r
+\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/filesystem.hpp>\r
+#include <boost/filesystem/fstream.hpp>\r
+#include <boost/regex.hpp>\r
+#include <boost/property_tree/xml_parser.hpp>\r
+#include <boost/locale.hpp>\r
+#include <boost/range/adaptor/transformed.hpp>\r
+#include <boost/range/algorithm/copy.hpp>\r
+#include <boost/archive/iterators/base64_from_binary.hpp>\r
+#include <boost/archive/iterators/insert_linebreaks.hpp>\r
+#include <boost/archive/iterators/transform_width.hpp>\r
+\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
+/* Return codes\r
+\r
+100 [action]                   Information om att något har hänt  \r
+101 [action]                   Information om att något har hänt, en rad data skickas  \r
+\r
+202 [kommando] OK              Kommandot har utförts  \r
+201 [kommando] OK              Kommandot har utförts, och en rad data skickas tillbaka  \r
+200 [kommando] OK              Kommandot har utförts, och flera rader data skickas tillbaka. Avslutas med tomrad  \r
+\r
+400 ERROR                              Kommandot kunde inte förstås  \r
+401 [kommando] ERROR   Ogiltig kanal  \r
+402 [kommando] ERROR   Parameter saknas  \r
+403 [kommando] ERROR   Ogiltig parameter  \r
+404 [kommando] ERROR   Mediafilen hittades inte  \r
+\r
+500 FAILED                             Internt configurationfel  \r
+501 [kommando] FAILED  Internt configurationfel  \r
+502 [kommando] FAILED  Oläslig mediafil  \r
+\r
+600 [kommando] FAILED  funktion ej implementerad\r
+*/\r
+\r
+namespace caspar { namespace protocol {\r
+\r
+using namespace core;\r
+\r
+std::wstring read_file_base64(const boost::filesystem::wpath& file)\r
+{\r
+       using namespace boost::archive::iterators;\r
+\r
+       boost::filesystem::ifstream filestream(file, std::ios::binary);\r
+\r
+       if (!filestream)\r
+               return L"";\r
+\r
+       // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/\r
+               \r
+       typedef\r
+               insert_linebreaks<         // insert line breaks every 76 characters\r
+                       base64_from_binary<    // convert binary values to base64 characters\r
+                               transform_width<   // retrieve 6 bit integers from a sequence of 8 bit bytes\r
+                                       const unsigned char *,\r
+                                       6,\r
+                                       8\r
+                               >\r
+                       >,\r
+                       76\r
+               >\r
+        base64_iterator; // compose all the above operations in to a new iterator\r
+       auto length = boost::filesystem::file_size(file);\r
+       std::vector<char> bytes;\r
+       bytes.resize(length);\r
+       filestream.read(bytes.data(), length);\r
+\r
+       int padding = 0;\r
+\r
+       while (bytes.size() % 3 != 0)\r
+       {\r
+               ++padding;\r
+               bytes.push_back(0x00);\r
+       }\r
+\r
+       std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length - padding));\r
+       result.insert(result.end(), padding, '=');\r
+\r
+       return widen(result);\r
+}\r
+\r
+std::wstring read_utf8_file(const boost::filesystem::wpath& file)\r
+{\r
+       std::wstringstream result;\r
+       boost::filesystem::wifstream filestream(file);\r
+\r
+       if (filestream) \r
+       {\r
+               // Consume BOM first\r
+               filestream.get();\r
+               // read all data\r
+               result << filestream.rdbuf();\r
+       }\r
+\r
+       return result.str();\r
+}\r
+\r
+std::wstring read_latin1_file(const boost::filesystem::wpath& file)\r
+{\r
+       boost::locale::generator gen;\r
+       gen.locale_cache_enabled(true);\r
+       gen.categories(boost::locale::codepage_facet);\r
+\r
+       std::stringstream result_stream;\r
+       boost::filesystem::ifstream filestream(file);\r
+       filestream.imbue(gen("en_US.ISO8859-1"));\r
+\r
+       if (filestream)\r
+       {\r
+               // read all data\r
+               result_stream << filestream.rdbuf();\r
+       }\r
+\r
+       std::string result = result_stream.str();\r
+       std::wstring widened_result;\r
+\r
+       // The first 255 codepoints in unicode is the same as in latin1\r
+       auto from_signed_to_signed = std::function<unsigned char(char)>(\r
+               [] (char c) { return static_cast<unsigned char>(c); }\r
+       );\r
+       boost::copy(\r
+               result | boost::adaptors::transformed(from_signed_to_signed),\r
+               std::back_inserter(widened_result));\r
+\r
+       return widened_result;\r
+}\r
+\r
+std::wstring read_file(const boost::filesystem::wpath& file)\r
+{\r
+       static const uint8_t BOM[] = {0xef, 0xbb, 0xbf};\r
+\r
+       if (!boost::filesystem::exists(file))\r
+       {\r
+               return L"";\r
+       }\r
+\r
+       if (boost::filesystem::file_size(file) >= 3)\r
+       {\r
+               boost::filesystem::ifstream bom_stream(file);\r
+\r
+               char header[3];\r
+               bom_stream.read(header, 3);\r
+               bom_stream.close();\r
+\r
+               if (std::memcmp(BOM, header, 3) == 0)\r
+                       return read_utf8_file(file);\r
+       }\r
+\r
+       return read_latin1_file(file);\r
+}\r
+\r
+std::wstring MediaInfo(const boost::filesystem::wpath& path)\r
+{\r
+       if(boost::filesystem::is_regular_file(path))\r
+       {\r
+               std::wstring clipttype = TEXT(" N/A ");\r
+               std::wstring extension = boost::to_upper_copy(path.extension());\r
+               if(extension == TEXT(".TGA") || extension == TEXT(".COL") || extension == L".PNG" || extension == L".JPEG" || extension == L".JPG" ||\r
+                       extension == L"GIF" || extension == L"BMP")\r
+                       clipttype = TEXT(" STILL ");\r
+               else if(extension == TEXT(".WAV") || extension == TEXT(".MP3"))\r
+                       clipttype = TEXT(" AUDIO ");\r
+               else if(extension == TEXT(".SWF") || extension == TEXT(".CT") || \r
+                           extension == TEXT(".DV") || extension == TEXT(".MOV") || \r
+                               extension == TEXT(".MPG") || extension == TEXT(".AVI") || \r
+                               extension == TEXT(".MP4") || extension == TEXT(".FLV") || \r
+                               extension == TEXT(".STGA") || \r
+                               caspar::ffmpeg::is_valid_file(path.file_string()))\r
+                       clipttype = TEXT(" MOVIE ");\r
+\r
+               if(clipttype != TEXT(" N/A "))\r
+               {               \r
+                       auto is_not_digit = [](char c){ return std::isdigit(c) == 0; };\r
+\r
+                       auto relativePath = boost::filesystem::wpath(path.file_string().substr(env::media_folder().size()-1, path.file_string().size()));\r
+\r
+                       auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(path)));\r
+                       writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), is_not_digit), writeTimeStr.end());\r
+                       auto writeTimeWStr = std::wstring(writeTimeStr.begin(), writeTimeStr.end());\r
+\r
+                       auto sizeStr = boost::lexical_cast<std::wstring>(boost::filesystem::file_size(path));\r
+                       sizeStr.erase(std::remove_if(sizeStr.begin(), sizeStr.end(), is_not_digit), sizeStr.end());\r
+                       auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end());\r
+                               \r
+                       auto str = relativePath.replace_extension(TEXT("")).external_file_string();\r
+                       if(str[0] == '\\' || str[0] == '/')\r
+                               str = std::wstring(str.begin() + 1, str.end());\r
+\r
+                       return std::wstring() + TEXT("\"") + str +\r
+                                       + TEXT("\" ") + clipttype +\r
+                                       + TEXT(" ") + sizeStr +\r
+                                       + TEXT(" ") + writeTimeWStr +\r
+                                       + TEXT("\r\n");         \r
+               }       \r
+       }\r
+       return L"";\r
+}\r
+\r
+std::wstring ListMedia()\r
+{      \r
+       std::wstringstream replyString;\r
+       for (boost::filesystem::wrecursive_directory_iterator itr(env::media_folder()), end; itr != end; ++itr) \r
+               replyString << MediaInfo(itr->path());\r
+       \r
+       return boost::to_upper_copy(replyString.str());\r
+}\r
+\r
+std::wstring ListTemplates() \r
+{\r
+       std::wstringstream replyString;\r
+\r
+       for (boost::filesystem::wrecursive_directory_iterator itr(env::template_folder()), end; itr != end; ++itr)\r
+       {               \r
+               if(boost::filesystem::is_regular_file(itr->path()) && (itr->path().extension() == L".ft" || itr->path().extension() == L".ct"))\r
+               {\r
+                       auto relativePath = boost::filesystem::wpath(itr->path().file_string().substr(env::template_folder().size()-1, itr->path().file_string().size()));\r
+\r
+                       auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(itr->path())));\r
+                       writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), [](char c){ return std::isdigit(c) == 0;}), writeTimeStr.end());\r
+                       auto writeTimeWStr = std::wstring(writeTimeStr.begin(), writeTimeStr.end());\r
+\r
+                       auto sizeStr = boost::lexical_cast<std::string>(boost::filesystem::file_size(itr->path()));\r
+                       sizeStr.erase(std::remove_if(sizeStr.begin(), sizeStr.end(), [](char c){ return std::isdigit(c) == 0;}), sizeStr.end());\r
+\r
+                       auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end());\r
+\r
+                       std::wstring dir = relativePath.parent_path().external_directory_string();\r
+                       std::wstring file = boost::to_upper_copy(relativePath.filename());\r
+                       relativePath = boost::filesystem::wpath(dir + L"/" + file);\r
+                                               \r
+                       auto str = relativePath.replace_extension(TEXT("")).external_file_string();\r
+                       boost::trim_if(str, boost::is_any_of("\\/"));\r
+\r
+                       replyString << TEXT("\"") << str\r
+                                               << TEXT("\" ") << sizeWStr\r
+                                               << TEXT(" ") << writeTimeWStr\r
+                                               << TEXT("\r\n");                \r
+               }\r
+       }\r
+       return replyString.str();\r
+}\r
+\r
+namespace amcp {\r
+       \r
+AMCPCommand::AMCPCommand() : channelIndex_(0), scheduling_(Default), layerIndex_(-1)\r
+{}\r
+\r
+void AMCPCommand::SendReply()\r
+{\r
+       if(!pClientInfo_) \r
+               return;\r
+\r
+       if(replyString_.empty())\r
+               return;\r
+       pClientInfo_->Send(replyString_);\r
+}\r
+\r
+void AMCPCommand::Clear() \r
+{\r
+       pChannel_->stage()->clear();\r
+       pClientInfo_.reset();\r
+       channelIndex_ = 0;\r
+       _parameters.clear();\r
+}\r
+\r
+bool DiagnosticsCommand::DoExecute()\r
+{      \r
+       try\r
+       {\r
+               diagnostics::show_graphs(true);\r
+\r
+               SetReplyString(TEXT("202 DIAG OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 DIAG FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool ChannelGridCommand::DoExecute()\r
+{\r
+       int index = 1;\r
+       auto self = GetChannels().back();\r
+       \r
+       std::vector<std::wstring> params;\r
+       params.push_back(L"SCREEN");\r
+       params.push_back(L"NAME");\r
+       params.push_back(L"Channel Grid Window");\r
+       auto screen = create_consumer(params);\r
+\r
+       self->output()->add(screen);\r
+\r
+       BOOST_FOREACH(auto channel, GetChannels())\r
+       {\r
+               if(channel != self)\r
+               {\r
+                       auto producer = create_channel_producer(self->mixer(), channel);                \r
+                       self->stage()->load(index, producer, false);\r
+                       self->stage()->play(index);\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       int n = GetChannels().size()-1;\r
+       double delta = 1.0/static_cast<double>(n);\r
+       for(int x = 0; x < n; ++x)\r
+       {\r
+               for(int y = 0; y < n; ++y)\r
+               {\r
+                       int index = x+y*n+1;\r
+                       auto transform = [=](frame_transform transform) -> frame_transform\r
+                       {               \r
+                               transform.fill_translation[0]   = x*delta;\r
+                               transform.fill_translation[1]   = y*delta;\r
+                               transform.fill_scale[0]                 = delta;\r
+                               transform.fill_scale[1]                 = delta;\r
+                               transform.clip_translation[0]   = x*delta;\r
+                               transform.clip_translation[1]   = y*delta;\r
+                               transform.clip_scale[0]                 = delta;\r
+                               transform.clip_scale[1]                 = delta;                        \r
+                               return transform;\r
+                       };\r
+                       self->stage()->apply_transform(index, transform);\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CallCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               auto what = _parameters.at(0);\r
+                               \r
+               boost::unique_future<std::wstring> result;\r
+               if(what == L"B" || what == L"F")\r
+               {\r
+                       std::wstring param;\r
+                       for(auto it = std::begin(_parameters2)+1; it != std::end(_parameters2); ++it, param += L" ")\r
+                               param += *it;\r
+                       result = GetChannel()->stage()->call(GetLayerIndex(), what == L"F", boost::trim_copy(param));\r
+               }\r
+               else\r
+               {\r
+                       std::wstring param;\r
+                       for(auto it = std::begin(_parameters2); it != std::end(_parameters2); ++it, param += L" ")\r
+                               param += *it;\r
+                       result = GetChannel()->stage()->call(GetLayerIndex(), true, boost::trim_copy(param));\r
+               }\r
+\r
+               if(!result.timed_wait(boost::posix_time::seconds(2)))\r
+                       BOOST_THROW_EXCEPTION(timed_out());\r
+                               \r
+               std::wstringstream replyString;\r
+               if(result.get().empty())\r
+                       replyString << TEXT("202 CALL OK\r\n");\r
+               else\r
+                       replyString << TEXT("201 CALL OK\r\n") << result.get() << L"\r\n";\r
+               \r
+               SetReplyString(replyString.str());\r
+\r
+               return true;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 CALL FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+// UGLY HACK\r
+tbb::concurrent_unordered_map<int, std::vector<stage::transform_tuple_t>> deferred_transforms;\r
+\r
+bool MixerCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {       \r
+               bool defer = _parameters.back() == L"DEFER";\r
+               if(defer)\r
+                       _parameters.pop_back();\r
+\r
+               std::vector<stage::transform_tuple_t> transforms;\r
+\r
+               if(_parameters[0] == L"KEYER" || _parameters[0] == L"IS_KEY")\r
+               {\r
+                       bool value = boost::lexical_cast<int>(_parameters.at(1));\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.is_key = value;\r
+                               return transform;                                       \r
+                       }, 0, L"linear"));\r
+               }\r
+               else if(_parameters[0] == L"OPACITY")\r
+               {\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+\r
+                       double value = boost::lexical_cast<double>(_parameters.at(1));\r
+                       \r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.opacity = value;\r
+                               return transform;                                       \r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT")\r
+               {\r
+                       int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
+                       std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
+                       double x        = boost::lexical_cast<double>(_parameters.at(1));\r
+                       double y        = boost::lexical_cast<double>(_parameters.at(2));\r
+                       double x_s      = boost::lexical_cast<double>(_parameters.at(3));\r
+                       double y_s      = boost::lexical_cast<double>(_parameters.at(4));\r
+\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) mutable -> frame_transform\r
+                       {\r
+                               transform.fill_translation[0]   = x;\r
+                               transform.fill_translation[1]   = y;\r
+                               transform.fill_scale[0]                 = x_s;\r
+                               transform.fill_scale[1]                 = y_s;\r
+                               transform.clip_translation[0]   = x;\r
+                               transform.clip_translation[1]   = y;\r
+                               transform.clip_scale[0]                 = x_s;\r
+                               transform.clip_scale[1]                 = y_s;\r
+                               return transform;\r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT")\r
+               {\r
+                       int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
+                       std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
+                       double x        = boost::lexical_cast<double>(_parameters.at(1));\r
+                       double y        = boost::lexical_cast<double>(_parameters.at(2));\r
+                       double x_s      = boost::lexical_cast<double>(_parameters.at(3));\r
+                       double y_s      = boost::lexical_cast<double>(_parameters.at(4));\r
+\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.clip_translation[0]   = x;\r
+                               transform.clip_translation[1]   = y;\r
+                               transform.clip_scale[0]                 = x_s;\r
+                               transform.clip_scale[1]                 = y_s;\r
+                               return transform;\r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"GRID")\r
+               {\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+                       int n = boost::lexical_cast<int>(_parameters.at(1));\r
+                       double delta = 1.0/static_cast<double>(n);\r
+                       for(int x = 0; x < n; ++x)\r
+                       {\r
+                               for(int y = 0; y < n; ++y)\r
+                               {\r
+                                       int index = x+y*n+1;\r
+                                       transforms.push_back(stage::transform_tuple_t(index, [=](frame_transform transform) -> frame_transform\r
+                                       {               \r
+                                               transform.fill_translation[0]   = x*delta;\r
+                                               transform.fill_translation[1]   = y*delta;\r
+                                               transform.fill_scale[0]                 = delta;\r
+                                               transform.fill_scale[1]                 = delta;\r
+                                               transform.clip_translation[0]   = x*delta;\r
+                                               transform.clip_translation[1]   = y*delta;\r
+                                               transform.clip_scale[0]                 = delta;\r
+                                               transform.clip_scale[1]                 = delta;                        \r
+                                               return transform;\r
+                                       }, duration, tween));\r
+                               }\r
+                       }\r
+               }\r
+               else if(_parameters[0] == L"BLEND")\r
+               {\r
+                       auto blend_str = _parameters.at(1);                                                             \r
+                       int layer = GetLayerIndex();\r
+                       GetChannel()->mixer()->set_blend_mode(GetLayerIndex(), get_blend_mode(blend_str));      \r
+               }\r
+               else if(_parameters[0] == L"MASTERVOLUME")\r
+               {\r
+                       float master_volume = boost::lexical_cast<float>(_parameters.at(1));\r
+                       GetChannel()->mixer()->set_master_volume(master_volume);\r
+               }\r
+               else if(_parameters[0] == L"BRIGHTNESS")\r
+               {\r
+                       auto value = boost::lexical_cast<double>(_parameters.at(1));\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.brightness = value;\r
+                               return transform;\r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"SATURATION")\r
+               {\r
+                       auto value = boost::lexical_cast<double>(_parameters.at(1));\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.saturation = value;\r
+                               return transform;\r
+                       }, duration, tween));   \r
+               }\r
+               else if(_parameters[0] == L"CONTRAST")\r
+               {\r
+                       auto value = boost::lexical_cast<double>(_parameters.at(1));\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.contrast = value;\r
+                               return transform;\r
+                       }, duration, tween));   \r
+               }\r
+               else if(_parameters[0] == L"LEVELS")\r
+               {\r
+                       levels value;\r
+                       value.min_input  = boost::lexical_cast<double>(_parameters.at(1));\r
+                       value.max_input  = boost::lexical_cast<double>(_parameters.at(2));\r
+                       value.gamma              = boost::lexical_cast<double>(_parameters.at(3));\r
+                       value.min_output = boost::lexical_cast<double>(_parameters.at(4));\r
+                       value.max_output = boost::lexical_cast<double>(_parameters.at(5));\r
+                       int duration = _parameters.size() > 6 ? boost::lexical_cast<int>(_parameters[6]) : 0;\r
+                       std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear";\r
+\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.levels = value;\r
+                               return transform;\r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"VOLUME")\r
+               {\r
+                       int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
+                       std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
+                       double value = boost::lexical_cast<double>(_parameters[1]);\r
+\r
+                       transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
+                       {\r
+                               transform.volume = value;\r
+                               return transform;\r
+                       }, duration, tween));\r
+               }\r
+               else if(_parameters[0] == L"CLEAR")\r
+               {\r
+                       int layer = GetLayerIndex(std::numeric_limits<int>::max());\r
+                       if (layer == std::numeric_limits<int>::max())\r
+                       {\r
+                               GetChannel()->stage()->clear_transforms();\r
+                               GetChannel()->mixer()->clear_blend_modes();\r
+                       }\r
+                       else\r
+                       {\r
+                               GetChannel()->stage()->clear_transforms(layer);\r
+                               GetChannel()->mixer()->clear_blend_mode(layer);\r
+                       }\r
+               }\r
+               else if(_parameters[0] == L"COMMIT")\r
+               {\r
+                       transforms = std::move(deferred_transforms[GetChannelIndex()]);\r
+               }\r
+               else\r
+               {\r
+                       SetReplyString(TEXT("404 MIXER ERROR\r\n"));\r
+                       return false;\r
+               }\r
+\r
+               if(defer)\r
+               {\r
+                       auto& defer_tranforms = deferred_transforms[GetChannelIndex()];\r
+                       defer_tranforms.insert(defer_tranforms.end(), transforms.begin(), transforms.end());\r
+               }\r
+               else\r
+                       GetChannel()->stage()->apply_transforms(transforms);\r
+       \r
+               SetReplyString(TEXT("202 MIXER OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("404 MIXER ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 MIXER FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool SwapCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               if(GetLayerIndex(-1) != -1)\r
+               {\r
+                       std::vector<std::string> strs;\r
+                       boost::split(strs, _parameters[0], boost::is_any_of("-"));\r
+                       \r
+                       auto ch1 = GetChannel();\r
+                       auto ch2 = GetChannels().at(boost::lexical_cast<int>(strs.at(0))-1);\r
+\r
+                       int l1 = GetLayerIndex();\r
+                       int l2 = boost::lexical_cast<int>(strs.at(1));\r
+\r
+                       ch1->stage()->swap_layer(l1, l2, ch2->stage());\r
+               }\r
+               else\r
+               {\r
+                       auto ch1 = GetChannel();\r
+                       auto ch2 = GetChannels().at(boost::lexical_cast<int>(_parameters[0])-1);\r
+                       ch1->stage()->swap_layers(ch2->stage());\r
+               }\r
+               \r
+               SetReplyString(TEXT("202 SWAP OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("404 SWAP ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 SWAP FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool AddCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               auto consumer = create_consumer(_parameters);\r
+               GetChannel()->output()->add(GetLayerIndex(consumer->index()), consumer);\r
+       \r
+               SetReplyString(TEXT("202 ADD OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("404 ADD ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 ADD FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool RemoveCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               auto index = GetLayerIndex(std::numeric_limits<int>::min());\r
+               if(index == std::numeric_limits<int>::min())\r
+                       index = create_consumer(_parameters)->index();\r
+\r
+               GetChannel()->output()->remove(index);\r
+\r
+               SetReplyString(TEXT("202 REMOVE OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("404 REMOVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 REMOVE FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool LoadCommand::DoExecute()\r
+{      \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               _parameters[0] = _parameters[0];\r
+               auto pFP = create_producer(GetChannel()->mixer(), _parameters);         \r
+               GetChannel()->stage()->load(GetLayerIndex(), pFP, true);\r
+       \r
+               SetReplyString(TEXT("202 LOAD OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("404 LOAD ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 LOAD FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+\r
+\r
+//std::function<std::wstring()> channel_cg_add_command::parse(const std::wstring& message, const std::vector<renderer::render_device_ptr>& channels)\r
+//{\r
+//     static boost::wregex expr(L"^CG\\s(?<video_channel>\\d+)-?(?<LAYER>\\d+)?\\sADD\\s(?<FLASH_LAYER>\\d+)\\s(?<TEMPLATE>\\S+)\\s?(?<START_LABEL>\\S\\S+)?\\s?(?<PLAY_ON_LOAD>\\d)?\\s?(?<DATA>.*)?");\r
+//\r
+//     boost::wsmatch what;\r
+//     if(!boost::regex_match(message, what, expr))\r
+//             return nullptr;\r
+//\r
+//     auto info = channel_info::parse(what, channels);\r
+//\r
+//     int flash_layer_index = boost::lexical_cast<int>(what["FLASH_LAYER"].str());\r
+//\r
+//     std::wstring templatename = what["TEMPLATE"].str();\r
+//     bool play_on_load = what["PLAY_ON_LOAD"].matched ? what["PLAY_ON_LOAD"].str() != L"0" : 0;\r
+//     std::wstring start_label = what["START_LABEL"].str();   \r
+//     std::wstring data = get_data(what["DATA"].str());\r
+//     \r
+//     boost::replace_all(templatename, "\"", "");\r
+//\r
+//     return [=]() -> std::wstring\r
+//     {       \r
+//             std::wstring fullFilename = flash::flash_producer::find_template(server::template_folder() + templatename);\r
+//             if(fullFilename.empty())\r
+//                     BOOST_THROW_EXCEPTION(file_not_found());\r
+//     \r
+//             std::wstring extension = boost::filesystem::wpath(fullFilename).extension();\r
+//             std::wstring filename = templatename;\r
+//             filename.append(extension);\r
+//\r
+//             flash::flash::get_default_cg_producer(info.video_channel, std::max<int>(DEFAULT_CHANNEL_LAYER+1, info.layer_index))\r
+//                     ->add(flash_layer_index, filename, play_on_load, start_label, data);\r
+//\r
+//             CASPAR_LOG(info) << L"Executed [amcp_channel_cg_add]";\r
+//             return L"";\r
+//     };\r
+\r
+bool LoadbgCommand::DoExecute()\r
+{\r
+       transition_info transitionInfo;\r
+       \r
+       bool bLoop = false;\r
+\r
+       // TRANSITION\r
+\r
+       std::wstring message;\r
+       for(size_t n = 0; n < _parameters.size(); ++n)\r
+               message += _parameters[n] + L" ";\r
+               \r
+       static const boost::wregex expr(L".*(?<TRANSITION>CUT|PUSH|SLIDE|WIPE|MIX)\\s*(?<DURATION>\\d+)\\s*(?<TWEEN>(LINEAR)|(EASE[^\\s]*))?\\s*(?<DIRECTION>FROMLEFT|FROMRIGHT|LEFT|RIGHT)?.*");\r
+       boost::wsmatch what;\r
+       if(boost::regex_match(message, what, expr))\r
+       {\r
+               auto transition = what["TRANSITION"].str();\r
+               transitionInfo.duration = lexical_cast_or_default<size_t>(what["DURATION"].str());\r
+               auto direction = what["DIRECTION"].matched ? what["DIRECTION"].str() : L"";\r
+               auto tween = what["TWEEN"].matched ? what["TWEEN"].str() : L"";\r
+               transitionInfo.tweener = get_tweener(tween);            \r
+\r
+               if(transition == TEXT("CUT"))\r
+                       transitionInfo.type = transition::cut;\r
+               else if(transition == TEXT("MIX"))\r
+                       transitionInfo.type = transition::mix;\r
+               else if(transition == TEXT("PUSH"))\r
+                       transitionInfo.type = transition::push;\r
+               else if(transition == TEXT("SLIDE"))\r
+                       transitionInfo.type = transition::slide;\r
+               else if(transition == TEXT("WIPE"))\r
+                       transitionInfo.type = transition::wipe;\r
+               \r
+               if(direction == TEXT("FROMLEFT"))\r
+                       transitionInfo.direction = transition_direction::from_left;\r
+               else if(direction == TEXT("FROMRIGHT"))\r
+                       transitionInfo.direction = transition_direction::from_right;\r
+               else if(direction == TEXT("LEFT"))\r
+                       transitionInfo.direction = transition_direction::from_right;\r
+               else if(direction == TEXT("RIGHT"))\r
+                       transitionInfo.direction = transition_direction::from_left;\r
+       }\r
+       \r
+       //Perform loading of the clip\r
+       try\r
+       {\r
+               _parameters[0] = _parameters[0];\r
+               auto pFP = create_producer(GetChannel()->mixer(), _parameters);\r
+               if(pFP == frame_producer::empty())\r
+                       BOOST_THROW_EXCEPTION(file_not_found() << msg_info(_parameters.size() > 0 ? narrow(_parameters[0]) : ""));\r
+\r
+               bool auto_play = std::find(_parameters.begin(), _parameters.end(), L"AUTO") != _parameters.end();\r
+\r
+               auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transitionInfo);\r
+               GetChannel()->stage()->load(GetLayerIndex(), pFP2, false, auto_play ? transitionInfo.duration : -1); // TODO: LOOP\r
+       \r
+               SetReplyString(TEXT("202 LOADBG OK\r\n"));\r
+\r
+               return true;\r
+       }\r
+       catch(file_not_found&)\r
+       {               \r
+               std::wstring params2;\r
+               for(auto it = _parameters.begin(); it != _parameters.end(); ++it)\r
+                       params2 += L" " + *it;\r
+               CASPAR_LOG(error) << L"File not found. No match found for parameters. Check syntax:" << params2;\r
+               SetReplyString(TEXT("404 LOADBG ERROR\r\n"));\r
+               return false;\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               SetReplyString(TEXT("502 LOADBG FAILED\r\n"));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool PauseCommand::DoExecute()\r
+{\r
+       try\r
+       {\r
+               GetChannel()->stage()->pause(GetLayerIndex());\r
+               SetReplyString(TEXT("202 PAUSE OK\r\n"));\r
+               return true;\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("501 PAUSE FAILED\r\n"));\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool PlayCommand::DoExecute()\r
+{\r
+       try\r
+       {\r
+               if(!_parameters.empty())\r
+               {\r
+                       LoadbgCommand lbg;\r
+                       lbg.SetChannel(GetChannel());\r
+                       lbg.SetChannelIndex(GetChannelIndex());\r
+                       lbg.SetLayerIntex(GetLayerIndex());\r
+                       lbg.SetClientInfo(GetClientInfo());\r
+                       for(auto it = _parameters.begin(); it != _parameters.end(); ++it)\r
+                               lbg.AddParameter(*it);\r
+                       if(!lbg.Execute())\r
+                               throw std::exception();\r
+               }\r
+\r
+               GetChannel()->stage()->play(GetLayerIndex());\r
+               \r
+               SetReplyString(TEXT("202 PLAY OK\r\n"));\r
+               return true;\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("501 PLAY FAILED\r\n"));\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool StopCommand::DoExecute()\r
+{\r
+       try\r
+       {\r
+               GetChannel()->stage()->stop(GetLayerIndex());\r
+               SetReplyString(TEXT("202 STOP OK\r\n"));\r
+               return true;\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("501 STOP FAILED\r\n"));\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool ClearCommand::DoExecute()\r
+{\r
+       int index = GetLayerIndex(std::numeric_limits<int>::min());\r
+       if(index != std::numeric_limits<int>::min())\r
+               GetChannel()->stage()->clear(index);\r
+       else\r
+               GetChannel()->stage()->clear();\r
+               \r
+       SetReplyString(TEXT("202 CLEAR OK\r\n"));\r
+\r
+       return true;\r
+}\r
+\r
+bool PrintCommand::DoExecute()\r
+{\r
+       GetChannel()->output()->add(create_consumer(boost::assign::list_of(L"IMAGE")));\r
+               \r
+       SetReplyString(TEXT("202 PRINT OK\r\n"));\r
+\r
+       return true;\r
+}\r
+\r
+bool LogCommand::DoExecute()\r
+{\r
+       if(_parameters.at(0) == L"LEVEL")\r
+               log::set_log_level(_parameters.at(1));\r
+\r
+       SetReplyString(TEXT("202 LOG OK\r\n"));\r
+\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecute()\r
+{\r
+       try\r
+       {\r
+               std::wstring command = _parameters[0];\r
+               if(command == TEXT("ADD"))\r
+                       return DoExecuteAdd();\r
+               else if(command == TEXT("PLAY"))\r
+                       return DoExecutePlay();\r
+               else if(command == TEXT("STOP"))\r
+                       return DoExecuteStop();\r
+               else if(command == TEXT("NEXT"))\r
+                       return DoExecuteNext();\r
+               else if(command == TEXT("REMOVE"))\r
+                       return DoExecuteRemove();\r
+               else if(command == TEXT("CLEAR"))\r
+                       return DoExecuteClear();\r
+               else if(command == TEXT("UPDATE"))\r
+                       return DoExecuteUpdate();\r
+               else if(command == TEXT("INVOKE"))\r
+                       return DoExecuteInvoke();\r
+               else if(command == TEXT("INFO"))\r
+                       return DoExecuteInfo();\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+       }\r
+\r
+       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+       return false;\r
+}\r
+\r
+bool CGCommand::ValidateLayer(const std::wstring& layerstring) {\r
+       int length = layerstring.length();\r
+       for(int i = 0; i < length; ++i) {\r
+               if(!_istdigit(layerstring[i])) {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteAdd() {\r
+       //CG 1 ADD 0 "template_folder/templatename" [STARTLABEL] 0/1 [DATA]\r
+\r
+       int layer = 0;                          //_parameters[1]\r
+//     std::wstring templateName;      //_parameters[2]\r
+       std::wstring label;             //_parameters[3]\r
+       bool bDoStart = false;          //_parameters[3] alt. _parameters[4]\r
+//     std::wstring data;                      //_parameters[4] alt. _parameters[5]\r
+\r
+       if(_parameters.size() < 4) \r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return false;\r
+       }\r
+       unsigned int dataIndex = 4;\r
+\r
+       if(!ValidateLayer(_parameters[1])) \r
+       {\r
+               SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       layer = _ttoi(_parameters[1].c_str());\r
+\r
+       if(_parameters[3].length() > 1) \r
+       {       //read label\r
+               label = _parameters2[3];\r
+               ++dataIndex;\r
+\r
+               if(_parameters.size() > 4 && _parameters[4].length() > 0)       //read play-on-load-flag\r
+                       bDoStart = (_parameters[4][0]==TEXT('1')) ? true : false;\r
+               else \r
+               {\r
+                       SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+       }\r
+       else if(_parameters[3].length() > 0) {  //read play-on-load-flag\r
+               bDoStart = (_parameters[3][0]==TEXT('1')) ? true : false;\r
+       }\r
+       else \r
+       {\r
+               SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       const TCHAR* pDataString = 0;\r
+       std::wstringstream data;\r
+       std::wstring dataFromFile;\r
+       if(_parameters.size() > dataIndex) \r
+       {       //read data\r
+               const std::wstring& dataString = _parameters2[dataIndex];\r
+\r
+               if(dataString[0] == TEXT('<')) //the data is an XML-string\r
+                       pDataString = dataString.c_str();\r
+               else \r
+               {\r
+                       //The data is not an XML-string, it must be a filename\r
+                       std::wstring filename = env::data_folder();\r
+                       filename.append(dataString);\r
+                       filename.append(TEXT(".ftd"));\r
+\r
+                       dataFromFile = read_file(boost::filesystem::wpath(filename));\r
+                       pDataString = dataFromFile.c_str();\r
+               }\r
+       }\r
+\r
+       std::wstring fullFilename = flash::find_template(env::template_folder() + _parameters[2]);\r
+       if(!fullFilename.empty())\r
+       {\r
+               std::wstring extension = boost::filesystem::wpath(fullFilename).extension();\r
+               std::wstring filename = _parameters[2];\r
+               filename.append(extension);\r
+\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->add(layer, filename, bDoStart, label, (pDataString!=0) ? pDataString : TEXT(""));\r
+               SetReplyString(TEXT("202 CG OK\r\n"));\r
+       }\r
+       else\r
+       {\r
+               CASPAR_LOG(warning) << "Could not find template " << _parameters[2];\r
+               SetReplyString(TEXT("404 CG ERROR\r\n"));\r
+       }\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecutePlay()\r
+{\r
+       if(_parameters.size() > 1)\r
+       {\r
+               if(!ValidateLayer(_parameters[1])) \r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->play(layer);\r
+       }\r
+       else\r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteStop() \r
+{\r
+       if(_parameters.size() > 1)\r
+       {\r
+               if(!ValidateLayer(_parameters[1])) \r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->stop(layer, 0);\r
+       }\r
+       else \r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteNext()\r
+{\r
+       if(_parameters.size() > 1) \r
+       {\r
+               if(!ValidateLayer(_parameters[1])) \r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->next(layer);\r
+       }\r
+       else \r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteRemove() \r
+{\r
+       if(_parameters.size() > 1) \r
+       {\r
+               if(!ValidateLayer(_parameters[1])) \r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->remove(layer);\r
+       }\r
+       else \r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteClear() \r
+{\r
+       GetChannel()->stage()->clear(GetLayerIndex(flash::cg_producer::DEFAULT_LAYER));\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteUpdate() \r
+{\r
+       try\r
+       {\r
+               if(!ValidateLayer(_parameters.at(1)))\r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+                                               \r
+               std::wstring dataString = _parameters2.at(2);                           \r
+               if(dataString.at(0) != TEXT('<'))\r
+               {\r
+                       //The data is not an XML-string, it must be a filename\r
+                       std::wstring filename = env::data_folder();\r
+                       filename.append(dataString);\r
+                       filename.append(TEXT(".ftd"));\r
+\r
+                       dataString = read_file(boost::filesystem::wpath(filename));\r
+               }               \r
+\r
+               int layer = _ttoi(_parameters.at(1).c_str());\r
+               flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->update(layer, dataString);\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+\r
+       SetReplyString(TEXT("202 CG OK\r\n"));\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteInvoke() \r
+{\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("201 CG OK\r\n");\r
+\r
+       if(_parameters.size() > 2)\r
+       {\r
+               if(!ValidateLayer(_parameters[1]))\r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               auto result = flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->invoke(layer, _parameters2[2]);\r
+               replyString << result << TEXT("\r\n"); \r
+       }\r
+       else \r
+       {\r
+               SetReplyString(TEXT("402 CG ERROR\r\n"));\r
+               return true;\r
+       }\r
+       \r
+       SetReplyString(replyString.str());\r
+       return true;\r
+}\r
+\r
+bool CGCommand::DoExecuteInfo() \r
+{\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("201 CG OK\r\n");\r
+\r
+       if(_parameters.size() > 1)\r
+       {\r
+               if(!ValidateLayer(_parameters[1]))\r
+               {\r
+                       SetReplyString(TEXT("403 CG ERROR\r\n"));\r
+                       return false;\r
+               }\r
+\r
+               int layer = _ttoi(_parameters[1].c_str());\r
+               auto desc = flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->description(layer);\r
+               \r
+               replyString << desc << TEXT("\r\n"); \r
+       }\r
+       else \r
+       {\r
+               auto info = flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->template_host_info();\r
+               replyString << info << TEXT("\r\n"); \r
+       }       \r
+\r
+       SetReplyString(replyString.str());\r
+       return true;\r
+}\r
+\r
+bool DataCommand::DoExecute()\r
+{\r
+       std::wstring command = _parameters[0];\r
+       if(command == TEXT("STORE"))\r
+               return DoExecuteStore();\r
+       else if(command == TEXT("RETRIEVE"))\r
+               return DoExecuteRetrieve();\r
+       else if(command == TEXT("REMOVE"))\r
+               return DoExecuteRemove();\r
+       else if(command == TEXT("LIST"))\r
+               return DoExecuteList();\r
+\r
+       SetReplyString(TEXT("403 DATA ERROR\r\n"));\r
+       return false;\r
+}\r
+\r
+bool DataCommand::DoExecuteStore() \r
+{\r
+       if(_parameters.size() < 3) \r
+       {\r
+               SetReplyString(TEXT("402 DATA STORE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstring filename = env::data_folder();\r
+       filename.append(_parameters[1]);\r
+       filename.append(TEXT(".ftd"));\r
+\r
+       auto data_path = boost::filesystem::wpath(\r
+                       boost::filesystem::wpath(filename).parent_path());\r
+       \r
+       if(!boost::filesystem::exists(data_path))\r
+               boost::filesystem::create_directories(data_path);\r
+\r
+       std::wofstream datafile(filename.c_str());\r
+\r
+       if(!datafile) \r
+       {\r
+               SetReplyString(TEXT("501 DATA STORE FAILED\r\n"));\r
+               return false;\r
+       }\r
+\r
+       datafile << static_cast<wchar_t>(65279); // UTF-8 BOM character\r
+       datafile << _parameters2[2] << std::flush;\r
+       datafile.close();\r
+\r
+       std::wstring replyString = TEXT("202 DATA STORE OK\r\n");\r
+       SetReplyString(replyString);\r
+       return true;\r
+}\r
+\r
+bool DataCommand::DoExecuteRetrieve() \r
+{\r
+       if(_parameters.size() < 2) \r
+       {\r
+               SetReplyString(TEXT("402 DATA RETRIEVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstring filename = env::data_folder();\r
+       filename.append(_parameters[1]);\r
+       filename.append(TEXT(".ftd"));\r
+\r
+       std::wstring file_contents = read_file(boost::filesystem::wpath(filename));\r
+\r
+       if (file_contents.empty()) \r
+       {\r
+               SetReplyString(TEXT("404 DATA RETRIEVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstringstream reply;\r
+       reply << TEXT("201 DATA RETRIEVE OK\r\n");\r
+\r
+       std::wstringstream file_contents_stream(file_contents);\r
+       std::wstring line;\r
+       bool bFirstLine = true;\r
+       while(std::getline(file_contents_stream, line))\r
+       {\r
+               if(!bFirstLine)\r
+                       reply << "\\n";\r
+               else\r
+                       bFirstLine = false;\r
+\r
+               reply << line;\r
+       }\r
+\r
+       reply << "\r\n";\r
+       SetReplyString(reply.str());\r
+       return true;\r
+}\r
+\r
+bool DataCommand::DoExecuteRemove() \r
+{ \r
+       if (_parameters.size() < 2) \r
+       {\r
+               SetReplyString(TEXT("402 DATA REMOVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstring filename = env::data_folder();\r
+       filename.append(_parameters[1]);\r
+       filename.append(TEXT(".ftd"));\r
+\r
+       if (!boost::filesystem::exists(filename)) \r
+       {\r
+               SetReplyString(TEXT("404 DATA REMOVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       if (!boost::filesystem::remove(filename))\r
+       {\r
+               SetReplyString(TEXT("403 DATA REMOVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       SetReplyString(TEXT("201 DATA REMOVE OK\r\n"));\r
+\r
+       return true;\r
+}\r
+\r
+bool DataCommand::DoExecuteList() \r
+{\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("200 DATA LIST OK\r\n");\r
+\r
+       for (boost::filesystem::wrecursive_directory_iterator itr(env::data_folder()), end; itr != end; ++itr)\r
+       {                       \r
+               if(boost::filesystem::is_regular_file(itr->path()))\r
+               {\r
+                       if(!boost::iequals(itr->path().extension(), L".ftd"))\r
+                               continue;\r
+                       \r
+                       auto relativePath = boost::filesystem::wpath(itr->path().file_string().substr(env::data_folder().size()-1, itr->path().file_string().size()));\r
+                       \r
+                       auto str = relativePath.replace_extension(TEXT("")).external_file_string();\r
+                       if(str[0] == '\\' || str[0] == '/')\r
+                               str = std::wstring(str.begin() + 1, str.end());\r
+\r
+                       replyString << str << TEXT("\r\n");     \r
+               }\r
+       }\r
+       \r
+       replyString << TEXT("\r\n");\r
+\r
+       SetReplyString(boost::to_upper_copy(replyString.str()));\r
+       return true;\r
+}\r
+\r
+bool ThumbnailCommand::DoExecute()\r
+{\r
+       std::wstring command = _parameters[0];\r
+\r
+       if (command == TEXT("RETRIEVE"))\r
+               return DoExecuteRetrieve();\r
+       else if (command == TEXT("LIST"))\r
+               return DoExecuteList();\r
+       else if (command == TEXT("GENERATE"))\r
+               return DoExecuteGenerate();\r
+       else if (command == TEXT("GENERATE_ALL"))\r
+               return DoExecuteGenerateAll();\r
+\r
+       SetReplyString(TEXT("403 THUMBNAIL ERROR\r\n"));\r
+       return false;\r
+}\r
+\r
+bool ThumbnailCommand::DoExecuteRetrieve() \r
+{\r
+       if(_parameters.size() < 2) \r
+       {\r
+               SetReplyString(TEXT("402 THUMBNAIL RETRIEVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstring filename = env::thumbnails_folder();\r
+       filename.append(_parameters[1]);\r
+       filename.append(TEXT(".png"));\r
+\r
+       std::wstring file_contents = read_file_base64(boost::filesystem::wpath(filename));\r
+\r
+       if (file_contents.empty())\r
+       {\r
+               SetReplyString(TEXT("404 THUMBNAIL RETRIEVE ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       std::wstringstream reply;\r
+\r
+       reply << L"201 THUMBNAIL RETRIEVE OK\r\n";\r
+       reply << file_contents;\r
+       reply << L"\r\n";\r
+       SetReplyString(reply.str());\r
+       return true;\r
+}\r
+\r
+bool ThumbnailCommand::DoExecuteList()\r
+{\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("200 THUMBNAIL LIST OK\r\n");\r
+\r
+       for (boost::filesystem::wrecursive_directory_iterator itr(env::thumbnails_folder()), end; itr != end; ++itr)\r
+       {                       \r
+               if(boost::filesystem::is_regular_file(itr->path()))\r
+               {\r
+                       if(!boost::iequals(itr->path().extension(), L".png"))\r
+                               continue;\r
+                       \r
+                       auto relativePath = boost::filesystem::wpath(itr->path().file_string().substr(env::thumbnails_folder().size()-1, itr->path().file_string().size()));\r
+                       \r
+                       auto str = relativePath.replace_extension(L"").external_file_string();\r
+                       if(str[0] == '\\' || str[0] == '/')\r
+                               str = std::wstring(str.begin() + 1, str.end());\r
+\r
+                       auto mtime = boost::filesystem::last_write_time(itr->path());\r
+                       auto mtime_readable = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(mtime));\r
+                       auto file_size = boost::filesystem::file_size(itr->path());\r
+\r
+                       replyString << L"\"" << str << L"\" " << widen(mtime_readable) << L" " << file_size << L"\r\n";\r
+               }\r
+       }\r
+       \r
+       replyString << TEXT("\r\n");\r
+\r
+       SetReplyString(boost::to_upper_copy(replyString.str()));\r
+       return true;\r
+}\r
+\r
+bool ThumbnailCommand::DoExecuteGenerate()\r
+{\r
+       if (_parameters.size() < 2) \r
+       {\r
+               SetReplyString(L"402 THUMBNAIL GENERATE ERROR\r\n");\r
+               return false;\r
+       }\r
+\r
+       auto thumb_gen = GetThumbGenerator();\r
+\r
+       if (thumb_gen)\r
+       {\r
+               thumb_gen->generate(_parameters[1]);\r
+               SetReplyString(L"200 THUMBNAIL GENERATE OK\r\n");\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               SetReplyString(L"500 THUMBNAIL GENERATE ERROR\r\n");\r
+               return false;\r
+       }\r
+}\r
+\r
+bool ThumbnailCommand::DoExecuteGenerateAll()\r
+{\r
+       auto thumb_gen = GetThumbGenerator();\r
+\r
+       if (thumb_gen)\r
+       {\r
+               thumb_gen->generate_all();\r
+               SetReplyString(L"200 THUMBNAIL GENERATE_ALL OK\r\n");\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               SetReplyString(L"500 THUMBNAIL GENERATE_ALL ERROR\r\n");\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CinfCommand::DoExecute()\r
+{\r
+       std::wstringstream replyString;\r
+       \r
+       try\r
+       {\r
+               std::wstring info;\r
+               for (boost::filesystem::wrecursive_directory_iterator itr(env::media_folder()), end; itr != end; ++itr)\r
+               {\r
+                       auto path = itr->path();\r
+                       auto file = path.replace_extension(L"").filename();\r
+                       if(boost::iequals(file, _parameters.at(0)))\r
+                               info += MediaInfo(itr->path()) + L"\r\n";\r
+               }\r
+\r
+               if(info.empty())\r
+               {\r
+                       SetReplyString(TEXT("404 CINF ERROR\r\n"));\r
+                       return false;\r
+               }\r
+               replyString << TEXT("200 CINF OK\r\n");\r
+               replyString << info << "\r\n";\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("404 CINF ERROR\r\n"));\r
+               return false;\r
+       }\r
+       \r
+       SetReplyString(replyString.str());\r
+       return true;\r
+}\r
+\r
+void GenerateChannelInfo(int index, const safe_ptr<core::video_channel>& pChannel, std::wstringstream& replyString)\r
+{\r
+       replyString << index+1 << TEXT(" ") << pChannel->get_video_format_desc().name << TEXT(" PLAYING") << TEXT("\r\n");\r
+}\r
+\r
+bool InfoCommand::DoExecute()\r
+{\r
+       std::wstringstream replyString;\r
+       \r
+       boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);\r
+\r
+       try\r
+       {\r
+               if(_parameters.size() >= 1 && _parameters[0] == L"TEMPLATE")\r
+               {               \r
+                       replyString << L"201 INFO TEMPLATE OK\r\n";\r
+\r
+                       // Needs to be extended for any file, not just flash.\r
+\r
+                       auto filename = flash::find_template(env::template_folder() + _parameters.at(1));\r
+                                               \r
+                       std::wstringstream str;\r
+                       str << widen(flash::read_template_meta_info(filename));\r
+                       boost::property_tree::wptree info;\r
+                       boost::property_tree::xml_parser::read_xml(str, info, boost::property_tree::xml_parser::trim_whitespace | boost::property_tree::xml_parser::no_comments);\r
+\r
+                       boost::property_tree::xml_parser::write_xml(replyString, info, w);\r
+               }\r
+               else if(_parameters.size() >= 1 && _parameters[0] == L"CONFIG")\r
+               {               \r
+                       replyString << L"201 INFO CONFIG OK\r\n";\r
+\r
+                       boost::property_tree::write_xml(replyString, caspar::env::properties(), w);\r
+               }\r
+               else if(_parameters.size() >= 1 && _parameters[0] == L"PATHS")\r
+               {\r
+                       replyString << L"201 INFO PATHS OK\r\n";\r
+\r
+                       boost::property_tree::wptree info;\r
+                       info.add_child(L"paths", caspar::env::properties().get_child(L"configuration.paths"));\r
+                       info.add(L"paths.initial-path", boost::filesystem2::initial_path<boost::filesystem2::wpath>().directory_string() + L"\\");\r
+\r
+                       boost::property_tree::write_xml(replyString, info, w);\r
+               }\r
+               else if(_parameters.size() >= 1 && _parameters[0] == L"SYSTEM")\r
+               {\r
+                       replyString << L"201 INFO SYSTEM OK\r\n";\r
+                       \r
+                       boost::property_tree::wptree info;\r
+                       \r
+                       info.add(L"system.name",                                        caspar::get_system_product_name());\r
+                       info.add(L"system.windows.name",                        caspar::get_win_product_name());\r
+                       info.add(L"system.windows.service-pack",        caspar::get_win_sp_version());\r
+                       info.add(L"system.cpu",                                         caspar::get_cpu_info());\r
+       \r
+                       BOOST_FOREACH(auto device, caspar::decklink::get_device_list())\r
+                               info.add(L"system.caspar.decklink.device", device);\r
+\r
+                       BOOST_FOREACH(auto device, caspar::bluefish::get_device_list())\r
+                               info.add(L"system.caspar.bluefish.device", device);\r
+                               \r
+                       info.add(L"system.caspar.flash",                                        caspar::flash::get_version());\r
+                       info.add(L"system.caspar.template-host",                        caspar::flash::get_cg_version());\r
+                       info.add(L"system.caspar.free-image",                           caspar::image::get_version());\r
+                       info.add(L"system.caspar.ffmpeg.avcodec",                       caspar::ffmpeg::get_avcodec_version());\r
+                       info.add(L"system.caspar.ffmpeg.avformat",                      caspar::ffmpeg::get_avformat_version());\r
+                       info.add(L"system.caspar.ffmpeg.avfilter",                      caspar::ffmpeg::get_avfilter_version());\r
+                       info.add(L"system.caspar.ffmpeg.avutil",                        caspar::ffmpeg::get_avutil_version());\r
+                       info.add(L"system.caspar.ffmpeg.swscale",                       caspar::ffmpeg::get_swscale_version());\r
+                                                                       \r
+                       boost::property_tree::write_xml(replyString, info, w);\r
+               }\r
+               else if(_parameters.size() >= 1 && _parameters[0] == L"SERVER")\r
+               {\r
+                       replyString << L"201 INFO SERVER OK\r\n";\r
+                       \r
+                       boost::property_tree::wptree info;\r
+\r
+                       int index = 0;\r
+                       BOOST_FOREACH(auto channel, channels_)\r
+                               info.add_child(L"channels.channel", channel->info())\r
+                                       .add(L"index", ++index);\r
+                       \r
+                       boost::property_tree::write_xml(replyString, info, w);\r
+               }\r
+               else // channel\r
+               {                       \r
+                       if(_parameters.size() >= 1)\r
+                       {\r
+                               replyString << TEXT("201 INFO OK\r\n");\r
+                               boost::property_tree::wptree info;\r
+\r
+                               std::vector<std::wstring> split;\r
+                               boost::split(split, _parameters[0], boost::is_any_of("-"));\r
+                                       \r
+                               int layer = std::numeric_limits<int>::min();\r
+                               int channel = boost::lexical_cast<int>(split[0]) - 1;\r
+\r
+                               if(split.size() > 1)\r
+                                       layer = boost::lexical_cast<int>(split[1]);\r
+                               \r
+                               if(layer == std::numeric_limits<int>::min())\r
+                               {       \r
+                                       info.add_child(L"channel", channels_.at(channel)->info())\r
+                                                       .add(L"index", channel);\r
+                               }\r
+                               else\r
+                               {\r
+                                       if(_parameters.size() >= 2)\r
+                                       {\r
+                                               if(_parameters[1] == L"B")\r
+                                                       info.add_child(L"producer", channels_.at(channel)->stage()->background(layer).get()->info());\r
+                                               else\r
+                                                       info.add_child(L"producer", channels_.at(channel)->stage()->foreground(layer).get()->info());\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               info.add_child(L"layer", channels_.at(channel)->stage()->info(layer).get())\r
+                                                       .add(L"index", layer);\r
+                                       }\r
+                               }\r
+                               boost::property_tree::xml_parser::write_xml(replyString, info, w);\r
+                       }\r
+                       else\r
+                       {\r
+                               // This is needed for backwards compatibility with old clients\r
+                               replyString << TEXT("200 INFO OK\r\n");\r
+                               for(size_t n = 0; n < channels_.size(); ++n)\r
+                                       GenerateChannelInfo(n, channels_[n], replyString);\r
+                       }\r
+\r
+               }\r
+       }\r
+       catch(...)\r
+       {\r
+               SetReplyString(TEXT("403 INFO ERROR\r\n"));\r
+               return false;\r
+       }\r
+\r
+       replyString << TEXT("\r\n");\r
+       SetReplyString(replyString.str());\r
+       return true;\r
+}\r
+\r
+bool ClsCommand::DoExecute()\r
+{\r
+/*\r
+               wav = audio\r
+               mp3 = audio\r
+               swf     = movie\r
+               dv  = movie\r
+               tga = still\r
+               col = still\r
+       */\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("200 CLS OK\r\n");\r
+       replyString << ListMedia();\r
+       replyString << TEXT("\r\n");\r
+       SetReplyString(boost::to_upper_copy(replyString.str()));\r
+       return true;\r
+}\r
+\r
+bool TlsCommand::DoExecute()\r
+{\r
+       std::wstringstream replyString;\r
+       replyString << TEXT("200 TLS OK\r\n");\r
+\r
+       replyString << ListTemplates();\r
+       replyString << TEXT("\r\n");\r
+\r
+       SetReplyString(replyString.str());\r
+       return true;\r
+}\r
+\r
+bool VersionCommand::DoExecute()\r
+{\r
+       std::wstring replyString = TEXT("201 VERSION OK\r\n") + env::version() + TEXT("\r\n");\r
+\r
+       if(_parameters.size() > 0)\r
+       {\r
+               if(_parameters[0] == L"FLASH")\r
+                       replyString = TEXT("201 VERSION OK\r\n") + flash::get_version() + TEXT("\r\n");\r
+               else if(_parameters[0] == L"TEMPLATEHOST")\r
+                       replyString = TEXT("201 VERSION OK\r\n") + flash::get_cg_version() + TEXT("\r\n");\r
+               else if(_parameters[0] != L"SERVER")\r
+                       replyString = TEXT("403 VERSION ERROR\r\n");\r
+       }\r
+\r
+       SetReplyString(replyString);\r
+       return true;\r
+}\r
+\r
+bool ByeCommand::DoExecute()\r
+{\r
+       GetClientInfo()->Disconnect();\r
+       return true;\r
+}\r
+\r
+bool SetCommand::DoExecute()\r
+{\r
+       std::wstring name = _parameters[0];\r
+       std::transform(name.begin(), name.end(), name.begin(), toupper);\r
+\r
+       std::wstring value = _parameters[1];\r
+       std::transform(value.begin(), value.end(), value.begin(), toupper);\r
+\r
+       if(name == TEXT("MODE"))\r
+       {\r
+               auto format_desc = core::video_format_desc::get(value);\r
+               if(format_desc.format != core::video_format::invalid)\r
+               {\r
+                       GetChannel()->set_video_format_desc(format_desc);\r
+                       SetReplyString(TEXT("202 SET MODE OK\r\n"));\r
+               }\r
+               else\r
+                       SetReplyString(TEXT("501 SET MODE FAILED\r\n"));\r
+       }\r
+       else\r
+       {\r
+               this->SetReplyString(TEXT("403 SET ERROR\r\n"));\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool KillCommand::DoExecute()\r
+{\r
+       GetShutdownServerNow().set_value(false); // False for not waiting until a key is pressed before terminating.\r
+       return true;\r
+}\r
+\r
+}      //namespace amcp\r
+}}     //namespace caspar
\ No newline at end of file
diff --git a/protocol/amcp/AMCPCommandsImpl.h b/protocol/amcp/AMCPCommandsImpl.h
new file mode 100644 (file)
index 0000000..37c4f2c
--- /dev/null
@@ -0,0 +1,217 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#ifndef __AMCPCOMMANDSIMPL_H__\r
+#define __AMCPCOMMANDSIMPL_H__\r
+\r
+#include "AMCPCommand.h"\r
+\r
+namespace caspar { namespace protocol {\r
+       \r
+std::wstring ListMedia();\r
+std::wstring ListTemplates();\r
+\r
+namespace amcp {\r
+       \r
+class ChannelGridCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"ChannelGridCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class DiagnosticsCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"DiagnosticsCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class CallCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"CallCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class MixerCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"MixerCommand";}\r
+       bool DoExecute();\r
+};\r
+       \r
+class AddCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"AddCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class RemoveCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"RemoveCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class SwapCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"SwapCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class LoadCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"LoadCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class LoadbgCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"LoadbgCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class PlayCommand: public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"PlayCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class PauseCommand: public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"PauseCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class StopCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"StopCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class ClearCommand : public AMCPCommandBase<true, ImmediatelyAndClear, 0>\r
+{\r
+       std::wstring print() const { return L"ClearCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class PrintCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"PrintCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class LogCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"LogCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class CGCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"CGCommand";}\r
+       bool DoExecute();\r
+       bool ValidateLayer(const std::wstring& layerstring);\r
+\r
+       bool DoExecuteAdd();\r
+       bool DoExecutePlay();\r
+       bool DoExecuteStop();\r
+       bool DoExecuteNext();\r
+       bool DoExecuteRemove();\r
+       bool DoExecuteClear();\r
+       bool DoExecuteUpdate();\r
+       bool DoExecuteInvoke();\r
+       bool DoExecuteInfo();\r
+};\r
+\r
+class DataCommand : public AMCPCommandBase<false, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"DataCommand";}\r
+       bool DoExecute();\r
+       bool DoExecuteStore();\r
+       bool DoExecuteRetrieve();\r
+       bool DoExecuteRemove();\r
+       bool DoExecuteList();\r
+};\r
+\r
+class ThumbnailCommand : public AMCPCommandBase<false, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"ThumbnailCommand";}\r
+       bool DoExecute();\r
+       bool DoExecuteRetrieve();\r
+       bool DoExecuteList();\r
+       bool DoExecuteGenerate();\r
+       bool DoExecuteGenerateAll();\r
+};\r
+\r
+class ClsCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"ClsCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class TlsCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"TlsCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class CinfCommand : public AMCPCommandBase<false, AddToQueue, 1>\r
+{\r
+       std::wstring print() const { return L"CinfCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class InfoCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+public:\r
+       std::wstring print() const { return L"InfoCommand";}\r
+       InfoCommand(const std::vector<safe_ptr<core::video_channel>>& channels) : channels_(channels){}\r
+       bool DoExecute();\r
+private:\r
+       const std::vector<safe_ptr<core::video_channel>>& channels_;\r
+};\r
+\r
+class VersionCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"VersionCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class ByeCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"ByeCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class SetCommand : public AMCPCommandBase<true, AddToQueue, 2>\r
+{\r
+       std::wstring print() const { return L"SetCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+class KillCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"KillCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+}      //namespace amcp\r
+}}     //namespace caspar\r
+\r
+#endif //__AMCPCOMMANDSIMPL_H__
\ No newline at end of file
diff --git a/protocol/amcp/AMCPProtocolStrategy.cpp b/protocol/amcp/AMCPProtocolStrategy.cpp
new file mode 100644 (file)
index 0000000..4398459
--- /dev/null
@@ -0,0 +1,418 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#include "../StdAfx.h"\r
+\r
+#include "AMCPProtocolStrategy.h"\r
+\r
+#include "../util/AsyncEventServer.h"\r
+#include "AMCPCommandsImpl.h"\r
+\r
+#include <stdio.h>\r
+#include <crtdbg.h>\r
+#include <string.h>\r
+#include <algorithm>\r
+#include <cctype>\r
+\r
+#include <boost/algorithm/string/trim.hpp>\r
+#include <boost/algorithm/string/split.hpp>\r
+#include <boost/algorithm/string/replace.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
+#endif\r
+\r
+namespace caspar { namespace protocol { namespace amcp {\r
+\r
+using IO::ClientInfoPtr;\r
+\r
+const std::wstring AMCPProtocolStrategy::MessageDelimiter = TEXT("\r\n");\r
+\r
+inline std::shared_ptr<core::video_channel> GetChannelSafe(unsigned int index, const std::vector<safe_ptr<core::video_channel>>& channels)\r
+{\r
+       return index < channels.size() ? std::shared_ptr<core::video_channel>(channels[index]) : nullptr;\r
+}\r
+\r
+AMCPProtocolStrategy::AMCPProtocolStrategy(\r
+               const std::vector<safe_ptr<core::video_channel>>& channels,\r
+               const std::shared_ptr<core::thumbnail_generator>& thumb_gen,\r
+               boost::promise<bool>& shutdown_server_now)\r
+       : channels_(channels)\r
+       , thumb_gen_(thumb_gen)\r
+       , shutdown_server_now_(shutdown_server_now)\r
+{\r
+       AMCPCommandQueuePtr pGeneralCommandQueue(new AMCPCommandQueue());\r
+       commandQueues_.push_back(pGeneralCommandQueue);\r
+\r
+\r
+       std::shared_ptr<core::video_channel> pChannel;\r
+       unsigned int index = -1;\r
+       //Create a commandpump for each video_channel\r
+       while((pChannel = GetChannelSafe(++index, channels_)) != 0) {\r
+               AMCPCommandQueuePtr pChannelCommandQueue(new AMCPCommandQueue());\r
+               std::wstring title = TEXT("video_channel ");\r
+\r
+               //HACK: Perform real conversion from int to string\r
+               TCHAR num = TEXT('1')+static_cast<TCHAR>(index);\r
+               title += num;\r
+               \r
+               commandQueues_.push_back(pChannelCommandQueue);\r
+       }\r
+}\r
+\r
+AMCPProtocolStrategy::~AMCPProtocolStrategy() {\r
+}\r
+\r
+void AMCPProtocolStrategy::Parse(const TCHAR* pData, int charCount, ClientInfoPtr pClientInfo)\r
+{\r
+       size_t pos;\r
+       std::wstring recvData(pData, charCount);\r
+       std::wstring availibleData = (pClientInfo != nullptr ? pClientInfo->currentMessage_ : L"") + recvData;\r
+\r
+       while(true) {\r
+               pos = availibleData.find(MessageDelimiter);\r
+               if(pos != std::wstring::npos)\r
+               {\r
+                       std::wstring message = availibleData.substr(0,pos);\r
+\r
+                       //This is where a complete message gets taken care of\r
+                       if(message.length() > 0) {\r
+                               ProcessMessage(message, pClientInfo);\r
+                       }\r
+\r
+                       std::size_t nextStartPos = pos + MessageDelimiter.length();\r
+                       if(nextStartPos < availibleData.length())\r
+                               availibleData = availibleData.substr(nextStartPos);\r
+                       else {\r
+                               availibleData.clear();\r
+                               break;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+       if(pClientInfo)\r
+               pClientInfo->currentMessage_ = availibleData;\r
+}\r
+\r
+void AMCPProtocolStrategy::ProcessMessage(const std::wstring& message, ClientInfoPtr& pClientInfo)\r
+{      \r
+       CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message << L"\\r\\n";\r
+       \r
+       bool bError = true;\r
+       MessageParserState state = New;\r
+\r
+       AMCPCommandPtr pCommand;\r
+\r
+       pCommand = InterpretCommandString(message, &state);\r
+\r
+       if(pCommand != 0) {\r
+               pCommand->SetClientInfo(pClientInfo);   \r
+               if(QueueCommand(pCommand))\r
+                       bError = false;\r
+               else\r
+                       state = GetChannel;\r
+       }\r
+\r
+       if(bError == true) {\r
+               std::wstringstream answer;\r
+               switch(state)\r
+               {\r
+               case GetCommand:\r
+                       answer << TEXT("400 ERROR\r\n") + message << "\r\n";\r
+                       break;\r
+               case GetChannel:\r
+                       answer << TEXT("401 ERROR\r\n");\r
+                       break;\r
+               case GetParameters:\r
+                       answer << TEXT("402 ERROR\r\n");\r
+                       break;\r
+               default:\r
+                       answer << TEXT("500 FAILED\r\n");\r
+                       break;\r
+               }\r
+               pClientInfo->Send(answer.str());\r
+       }\r
+}\r
+\r
+AMCPCommandPtr AMCPProtocolStrategy::InterpretCommandString(const std::wstring& message, MessageParserState* pOutState)\r
+{\r
+       std::vector<std::wstring> tokens;\r
+       unsigned int currentToken = 0;\r
+       std::wstring commandSwitch;\r
+\r
+       AMCPCommandPtr pCommand;\r
+       MessageParserState state = New;\r
+\r
+       std::size_t tokensInMessage = TokenizeMessage(message, &tokens);\r
+\r
+       //parse the message one token at the time\r
+       while(currentToken < tokensInMessage)\r
+       {\r
+               switch(state)\r
+               {\r
+               case New:\r
+                       if(tokens[currentToken][0] == TEXT('/'))\r
+                               state = GetSwitch;\r
+                       else\r
+                               state = GetCommand;\r
+                       break;\r
+\r
+               case GetSwitch:\r
+                       commandSwitch = tokens[currentToken];\r
+                       state = GetCommand;\r
+                       ++currentToken;\r
+                       break;\r
+\r
+               case GetCommand:\r
+                       pCommand = CommandFactory(tokens[currentToken]);\r
+                       if(pCommand == 0) {\r
+                               goto ParseFinnished;\r
+                       }\r
+                       else\r
+                       {\r
+                               pCommand->SetChannels(channels_);\r
+                               pCommand->SetThumbGenerator(thumb_gen_);\r
+                               pCommand->SetShutdownServerNow(shutdown_server_now_);\r
+                               //Set scheduling\r
+                               if(commandSwitch.size() > 0) {\r
+                                       transform(commandSwitch.begin(), commandSwitch.end(), commandSwitch.begin(), toupper);\r
+\r
+                                       if(commandSwitch == TEXT("/APP"))\r
+                                               pCommand->SetScheduling(AddToQueue);\r
+                                       else if(commandSwitch  == TEXT("/IMMF"))\r
+                                               pCommand->SetScheduling(ImmediatelyAndClear);\r
+                               }\r
+\r
+                               if(pCommand->NeedChannel())\r
+                                       state = GetChannel;\r
+                               else\r
+                                       state = GetParameters;\r
+                       }\r
+                       ++currentToken;\r
+                       break;\r
+\r
+               case GetParameters:\r
+                       {\r
+                               _ASSERTE(pCommand != 0);\r
+                               int parameterCount=0;\r
+                               while(currentToken<tokensInMessage)\r
+                               {\r
+                                       pCommand->AddParameter(tokens[currentToken++]);\r
+                                       ++parameterCount;\r
+                               }\r
+\r
+                               if(parameterCount < pCommand->GetMinimumParameters()) {\r
+                                       goto ParseFinnished;\r
+                               }\r
+\r
+                               state = Done;\r
+                               break;\r
+                       }\r
+\r
+               case GetChannel:\r
+                       {\r
+//                             assert(pCommand != 0);\r
+\r
+                               std::wstring str = boost::trim_copy(tokens[currentToken]);\r
+                               std::vector<std::wstring> split;\r
+                               boost::split(split, str, boost::is_any_of("-"));\r
+                                       \r
+                               int channelIndex = -1;\r
+                               int layerIndex = -1;\r
+                               try\r
+                               {\r
+                                       channelIndex = boost::lexical_cast<int>(split[0]) - 1;\r
+\r
+                                       if(split.size() > 1)\r
+                                               layerIndex = boost::lexical_cast<int>(split[1]);\r
+                               }\r
+                               catch(...)\r
+                               {\r
+                                       goto ParseFinnished;\r
+                               }\r
+\r
+                               std::shared_ptr<core::video_channel> pChannel = GetChannelSafe(channelIndex, channels_);\r
+                               if(pChannel == 0) {\r
+                                       goto ParseFinnished;\r
+                               }\r
+\r
+                               pCommand->SetChannel(pChannel);\r
+                               pCommand->SetChannelIndex(channelIndex);\r
+                               pCommand->SetLayerIntex(layerIndex);\r
+\r
+                               state = GetParameters;\r
+                               ++currentToken;\r
+                               break;\r
+                       }\r
+\r
+               default:        //Done and unexpected\r
+                       goto ParseFinnished;\r
+               }\r
+       }\r
+\r
+ParseFinnished:\r
+       if(state == GetParameters && pCommand->GetMinimumParameters()==0)\r
+               state = Done;\r
+\r
+       if(state != Done) {\r
+               pCommand.reset();\r
+       }\r
+\r
+       if(pOutState != 0) {\r
+               *pOutState = state;\r
+       }\r
+\r
+       return pCommand;\r
+}\r
+\r
+bool AMCPProtocolStrategy::QueueCommand(AMCPCommandPtr pCommand) {\r
+       if(pCommand->NeedChannel()) {\r
+               unsigned int channelIndex = pCommand->GetChannelIndex() + 1;\r
+               if(commandQueues_.size() > channelIndex) {\r
+                       commandQueues_[channelIndex]->AddCommand(pCommand);\r
+               }\r
+               else\r
+                       return false;\r
+       }\r
+       else {\r
+               commandQueues_[0]->AddCommand(pCommand);\r
+       }\r
+       return true;\r
+}\r
+\r
+AMCPCommandPtr AMCPProtocolStrategy::CommandFactory(const std::wstring& str)\r
+{\r
+       std::wstring s = str;\r
+       transform(s.begin(), s.end(), s.begin(), toupper);\r
+       \r
+       if         (s == TEXT("MIXER"))                 return std::make_shared<MixerCommand>();\r
+       else if(s == TEXT("DIAG"))                      return std::make_shared<DiagnosticsCommand>();\r
+       else if(s == TEXT("CHANNEL_GRID"))      return std::make_shared<ChannelGridCommand>();\r
+       else if(s == TEXT("CALL"))                      return std::make_shared<CallCommand>();\r
+       else if(s == TEXT("SWAP"))                      return std::make_shared<SwapCommand>();\r
+       else if(s == TEXT("LOAD"))                      return std::make_shared<LoadCommand>();\r
+       else if(s == TEXT("LOADBG"))            return std::make_shared<LoadbgCommand>();\r
+       else if(s == TEXT("ADD"))                       return std::make_shared<AddCommand>();\r
+       else if(s == TEXT("REMOVE"))            return std::make_shared<RemoveCommand>();\r
+       else if(s == TEXT("PAUSE"))                     return std::make_shared<PauseCommand>();\r
+       else if(s == TEXT("PLAY"))                      return std::make_shared<PlayCommand>();\r
+       else if(s == TEXT("STOP"))                      return std::make_shared<StopCommand>();\r
+       else if(s == TEXT("CLEAR"))                     return std::make_shared<ClearCommand>();\r
+       else if(s == TEXT("PRINT"))                     return std::make_shared<PrintCommand>();\r
+       else if(s == TEXT("LOG"))                       return std::make_shared<LogCommand>();\r
+       else if(s == TEXT("CG"))                        return std::make_shared<CGCommand>();\r
+       else if(s == TEXT("DATA"))                      return std::make_shared<DataCommand>();\r
+       else if(s == TEXT("CINF"))                      return std::make_shared<CinfCommand>();\r
+       else if(s == TEXT("INFO"))                      return std::make_shared<InfoCommand>(channels_);\r
+       else if(s == TEXT("CLS"))                       return std::make_shared<ClsCommand>();\r
+       else if(s == TEXT("TLS"))                       return std::make_shared<TlsCommand>();\r
+       else if(s == TEXT("VERSION"))           return std::make_shared<VersionCommand>();\r
+       else if(s == TEXT("BYE"))                       return std::make_shared<ByeCommand>();\r
+       else if(s == TEXT("SET"))                       return std::make_shared<SetCommand>();\r
+       else if(s == TEXT("THUMBNAIL"))         return std::make_shared<ThumbnailCommand>();\r
+       //else if(s == TEXT("MONITOR"))\r
+       //{\r
+       //      result = AMCPCommandPtr(new MonitorCommand());\r
+       //}\r
+       else if(s == TEXT("KILL"))                      return std::make_shared<KillCommand>();\r
+       return nullptr;\r
+}\r
+\r
+std::size_t AMCPProtocolStrategy::TokenizeMessage(const std::wstring& message, std::vector<std::wstring>* pTokenVector)\r
+{\r
+       //split on whitespace but keep strings within quotationmarks\r
+       //treat \ as the start of an escape-sequence: the following char will indicate what to actually put in the string\r
+\r
+       std::wstring currentToken;\r
+\r
+       char inQuote = 0;\r
+       bool getSpecialCode = false;\r
+\r
+       for(unsigned int charIndex=0; charIndex<message.size(); ++charIndex)\r
+       {\r
+               if(getSpecialCode)\r
+               {\r
+                       //insert code-handling here\r
+                       switch(message[charIndex])\r
+                       {\r
+                       case TEXT('\\'):\r
+                               currentToken += TEXT("\\");\r
+                               break;\r
+                       case TEXT('\"'):\r
+                               currentToken += TEXT("\"");\r
+                               break;\r
+                       case TEXT('n'):\r
+                               currentToken += TEXT("\n");\r
+                               break;\r
+                       default:\r
+                               break;\r
+                       };\r
+                       getSpecialCode = false;\r
+                       continue;\r
+               }\r
+\r
+               if(message[charIndex]==TEXT('\\'))\r
+               {\r
+                       getSpecialCode = true;\r
+                       continue;\r
+               }\r
+\r
+               if(message[charIndex]==' ' && inQuote==false)\r
+               {\r
+                       if(currentToken.size()>0)\r
+                       {\r
+                               pTokenVector->push_back(currentToken);\r
+                               currentToken.clear();\r
+                       }\r
+                       continue;\r
+               }\r
+\r
+               if(message[charIndex]==TEXT('\"'))\r
+               {\r
+                       inQuote ^= 1;\r
+\r
+                       if(currentToken.size()>0)\r
+                       {\r
+                               pTokenVector->push_back(currentToken);\r
+                               currentToken.clear();\r
+                       }\r
+                       continue;\r
+               }\r
+\r
+               currentToken += message[charIndex];\r
+       }\r
+\r
+       if(currentToken.size()>0)\r
+       {\r
+               pTokenVector->push_back(currentToken);\r
+               currentToken.clear();\r
+       }\r
+\r
+       return pTokenVector->size();\r
+}\r
+\r
+}      //namespace amcp\r
+}}     //namespace caspar
\ No newline at end of file
diff --git a/protocol/amcp/AMCPProtocolStrategy.h b/protocol/amcp/AMCPProtocolStrategy.h
new file mode 100644 (file)
index 0000000..46f00ec
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../util/protocolstrategy.h"\r
+#include <core/video_channel.h>\r
+#include <core/thumbnail_generator.h>\r
+\r
+#include "AMCPCommand.h"\r
+#include "AMCPCommandQueue.h"\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+namespace caspar { namespace protocol { namespace amcp {\r
+\r
+class AMCPProtocolStrategy : public IO::IProtocolStrategy, boost::noncopyable\r
+{\r
+       enum MessageParserState {\r
+               New = 0,\r
+               GetSwitch,\r
+               GetCommand,\r
+               GetParameters,\r
+               GetChannel,\r
+               Done\r
+       };\r
+\r
+       AMCPProtocolStrategy(const AMCPProtocolStrategy&);\r
+       AMCPProtocolStrategy& operator=(const AMCPProtocolStrategy&);\r
+\r
+public:\r
+       AMCPProtocolStrategy(\r
+                       const std::vector<safe_ptr<core::video_channel>>& channels,\r
+                       const std::shared_ptr<core::thumbnail_generator>& thumb_gen,\r
+                       boost::promise<bool>& shutdown_server_now);\r
+       virtual ~AMCPProtocolStrategy();\r
+\r
+       virtual void Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo);\r
+       virtual UINT GetCodepage() {\r
+               return CP_UTF8;\r
+       }\r
+\r
+       AMCPCommandPtr InterpretCommandString(const std::wstring& str, MessageParserState* pOutState=0);\r
+\r
+private:\r
+       friend class AMCPCommand;\r
+\r
+       void ProcessMessage(const std::wstring& message, IO::ClientInfoPtr& pClientInfo);\r
+       std::size_t TokenizeMessage(const std::wstring& message, std::vector<std::wstring>* pTokenVector);\r
+       AMCPCommandPtr CommandFactory(const std::wstring& str);\r
+\r
+       bool QueueCommand(AMCPCommandPtr);\r
+\r
+       std::vector<safe_ptr<core::video_channel>> channels_;\r
+       std::shared_ptr<core::thumbnail_generator> thumb_gen_;\r
+       boost::promise<bool>& shutdown_server_now_;\r
+       std::vector<AMCPCommandQueuePtr> commandQueues_;\r
+       static const std::wstring MessageDelimiter;\r
+};\r
+\r
+}}}\r
diff --git a/protocol/cii/CIICommand.h b/protocol/cii/CIICommand.h
new file mode 100644 (file)
index 0000000..ea9146f
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#pragma once\r
+\r
+namespace caspar { namespace protocol {\r
+namespace cii {\r
+\r
+class ICIICommand\r
+{\r
+public:\r
+       virtual ~ICIICommand() {}\r
+       virtual int GetMinimumParameters() = 0;\r
+       virtual void Setup(const std::vector<std::wstring>& parameters) = 0;\r
+\r
+       virtual void Execute() = 0;\r
+};\r
+typedef std::tr1::shared_ptr<ICIICommand> CIICommandPtr;\r
+\r
+}      //namespace cii\r
+}}     //namespace caspar
\ No newline at end of file
diff --git a/protocol/cii/CIICommandsImpl.cpp b/protocol/cii/CIICommandsImpl.cpp
new file mode 100644 (file)
index 0000000..3253097
--- /dev/null
@@ -0,0 +1,207 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#include "../StdAfx.h"\r
+\r
+#pragma warning (disable: 4244)\r
+\r
+#include "CIIProtocolStrategy.h"\r
+#include "CIICommandsImpl.h"\r
+#include <sstream>\r
+#include <algorithm>\r
+#include <modules/flash/producer/cg_producer.h>\r
+#include <boost/locale.hpp>\r
+\r
+namespace caspar { namespace protocol { namespace cii {\r
+\r
+/////////////////\r
+// MediaCommand\r
+void MediaCommand::Setup(const std::vector<std::wstring>& parameters) \r
+{\r
+       graphicProfile_ = parameters[1].substr(2);\r
+}\r
+\r
+void MediaCommand::Execute() \r
+{\r
+       pCIIStrategy_->SetProfile(graphicProfile_);\r
+}\r
+\r
+\r
+/////////////////\r
+// WriteCommand\r
+void WriteCommand::Setup(const std::vector<std::wstring>& parameters)\r
+{\r
+       try \r
+       {\r
+               if(parameters.size() > 2)\r
+               {\r
+                       targetName_ = parameters[1];\r
+                       templateName_ = parameters[2];\r
+\r
+                       std::wstringstream dataStream;\r
+\r
+                       dataStream << TEXT("<templateData>");\r
+\r
+                       std::vector<std::wstring>::size_type end = parameters.size();\r
+                       for(std::vector<std::wstring>::size_type i = 3; i < end; ++i) \r
+                               dataStream << TEXT("<componentData id=\"field") << i-2 << TEXT("\"><data id=\"text\" value=\"") << parameters[i] << TEXT("\" /></componentData>"); \r
+\r
+                       dataStream << TEXT("</templateData>");\r
+                       xmlData_ = dataStream.str();\r
+               }\r
+       }\r
+       catch(std::exception) {\r
+       }\r
+}\r
+\r
+void WriteCommand::Execute() \r
+{\r
+       pCIIStrategy_->WriteTemplateData(templateName_, targetName_, xmlData_);\r
+}\r
+\r
+\r
+//////////////////////\r
+// ImagestoreCommand\r
+void ImagestoreCommand::Setup(const std::vector<std::wstring>& parameters) \r
+{\r
+       if(parameters[1] == TEXT("7") && parameters.size() > 2) \r
+               titleName_ = parameters[2].substr(0, 4);        \r
+}\r
+\r
+void ImagestoreCommand::Execute()\r
+{\r
+       pCIIStrategy_->DisplayTemplate(titleName_);\r
+}\r
+\r
+\r
+//////////////////////\r
+// MiscellaneousCommand\r
+void MiscellaneousCommand::Setup(const std::vector<std::wstring>& parameters)\r
+{\r
+       //HAWRYS:       V\5\3\1\1\namn.tga\1\r
+       //                      Display still\r
+       if((parameters.size() > 5) && parameters[1] == TEXT("5") && parameters[2] == TEXT("3"))\r
+       {\r
+               filename_ = parameters[5];\r
+               filename_ = filename_.substr(0, filename_.find_last_of(TEXT('.')));\r
+               filename_.append(L".ft");\r
+               state_ = 0;\r
+               return;\r
+       }\r
+       \r
+       //NEPTUNE:      V\5\13\1\X\Template\0\TabField1\TabField2...\r
+       //                      Add Template to layer X in the active templatehost\r
+       if((parameters.size() > 5) && parameters[1] == TEXT("5") && parameters[2] == TEXT("13"))\r
+       {\r
+               layer_ = _ttoi(parameters[4].c_str());\r
+               filename_ = parameters[5];\r
+               if(filename_.find(L"PK/") == std::wstring::npos && filename_.find(L"PK\\") == std::wstring::npos)\r
+                       filename_ = L"PK/" + filename_;\r
+\r
+               state_ = 1;\r
+               if(parameters.size() > 7) {\r
+                       std::wstringstream dataStream;\r
+\r
+                       dataStream << TEXT("<templateData>");\r
+                       std::vector<std::wstring>::size_type end = parameters.size();\r
+                       for(std::vector<std::wstring>::size_type i = 7; i < end; ++i) {\r
+                               dataStream << TEXT("<componentData id=\"f") << i-7 << TEXT("\"><data id=\"text\" value=\"") << parameters[i] << TEXT("\" /></componentData>"); \r
+                       }\r
+                       dataStream << TEXT("</templateData>");\r
+\r
+                       xmlData_ = dataStream.str();\r
+               }\r
+       }\r
+\r
+       // VIDEO MODE V\5\14\MODE\r
+       if((parameters.size() > 3) && parameters[1] == TEXT("5") && parameters[2] == TEXT("14"))\r
+       {\r
+               std::wstring value = parameters[3];\r
+               std::transform(value.begin(), value.end(), value.begin(), toupper);\r
+\r
+               this->pCIIStrategy_->GetChannel()->set_video_format_desc(core::video_format_desc::get(value));\r
+       }\r
+}\r
+\r
+void MiscellaneousCommand::Execute() \r
+{\r
+       if(state_ == 0)\r
+               pCIIStrategy_->DisplayMediaFile(filename_);     \r
+\r
+       //TODO: Need to be checked for validity\r
+       else if(state_ == 1)            \r
+       {\r
+               // HACK fix. The data sent is UTF8, however the protocol is implemented for ISO-8859-1. Instead of doing risky changes we simply convert into proper encoding when leaving protocol code.\r
+               auto xmlData2 = boost::locale::conv::utf_to_utf<wchar_t, char>(std::string(xmlData_.begin(), xmlData_.end()));\r
+               flash::get_default_cg_producer(pCIIStrategy_->GetChannel())->add(layer_, filename_, false, TEXT(""), xmlData2);\r
+       }\r
+}\r
+\r
+\r
+///////////////////\r
+// KeydataCommand\r
+void KeydataCommand::Execute() \r
+{\r
+       if(state_ == 0) \r
+               pCIIStrategy_->DisplayTemplate(titleName_);\r
+       \r
+\r
+       //TODO: Need to be checked for validity\r
+       else if(state_ == 1)\r
+               flash::get_default_cg_producer(pCIIStrategy_->GetChannel())->stop(layer_, 0);\r
+       else if(state_ == 2)\r
+               pCIIStrategy_->GetChannel()->stage()->clear(flash::cg_producer::DEFAULT_LAYER);\r
+       else if(state_ == 3)\r
+               flash::get_default_cg_producer(pCIIStrategy_->GetChannel())->play(layer_);\r
+}\r
+\r
+void KeydataCommand::Setup(const std::vector<std::wstring>& parameters) {\r
+       //HAWRYS:       Y\<205><247><202><196><192><192><200><248>\r
+       //parameter[1] looks like this: "=g:XXXXh" where XXXX is the name that we want\r
+       if(parameters[1].size() > 6) \r
+       {\r
+               titleName_.resize(4);\r
+               for(int i=0;i<4;++i)\r
+               {\r
+                       if(parameters[1][i+3] < 176) {\r
+                               titleName_ = TEXT("");\r
+                               break;\r
+                       }\r
+                       titleName_[i] = parameters[1][i+3]-144;\r
+               }\r
+               state_ = 0;\r
+       }\r
+\r
+       if(parameters.size() > 2)       \r
+               layer_ = _ttoi(parameters[2].c_str());  \r
+\r
+       if(parameters[1].at(0) == 27)   //NEPTUNE:      Y\<27>\X                        Stop layer X.\r
+               state_ = 1;\r
+       else if(static_cast<unsigned char>(parameters[1].at(1)) == 190) //NEPTUNE:      Y\<254>                 Clear Canvas. \r
+               state_ = 2;\r
+       else if(static_cast<unsigned char>(parameters[1].at(1)) == 149) //NEPTUNE:      Y\<213><243>\X  Play layer X. \r
+               state_ = 3;                                                                                                     //UPDATE 2011-05-09: These char-codes are aparently not valid after converting to wide-chars\r
+                                                                                                                                       //the correct sequence is <195><149><195><179> \r
+               \r
+}\r
+\r
+}}}
\ No newline at end of file
diff --git a/protocol/cii/CIICommandsImpl.h b/protocol/cii/CIICommandsImpl.h
new file mode 100644 (file)
index 0000000..166fff5
--- /dev/null
@@ -0,0 +1,136 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#pragma once\r
+\r
+#include "ciicommand.h"\r
+\r
+namespace caspar { namespace protocol {\r
+\r
+namespace cii {\r
+\r
+class CIIProtocolStrategy;\r
+\r
+class MediaCommand : public ICIICommand\r
+{\r
+public:\r
+       MediaCommand(CIIProtocolStrategy* pPS) : pCIIStrategy_(pPS)\r
+       {}\r
+\r
+       virtual int GetMinimumParameters() {\r
+               return 1;\r
+       }\r
+\r
+       virtual void Setup(const std::vector<std::wstring>& parameters);\r
+       virtual void Execute();\r
+\r
+private:\r
+       std::wstring graphicProfile_;\r
+\r
+       CIIProtocolStrategy* pCIIStrategy_;\r
+};\r
+\r
+class WriteCommand : public ICIICommand\r
+{\r
+public:\r
+       WriteCommand(CIIProtocolStrategy* pPS) : pCIIStrategy_(pPS)\r
+       {}\r
+\r
+       virtual int GetMinimumParameters() {\r
+               return 2;\r
+       }\r
+\r
+       virtual void Setup(const std::vector<std::wstring>& parameters);\r
+       virtual void Execute();\r
+\r
+private:\r
+       std::wstring targetName_;\r
+       std::wstring templateName_;\r
+       std::wstring xmlData_;\r
+\r
+       CIIProtocolStrategy* pCIIStrategy_;\r
+};\r
+\r
+class MiscellaneousCommand : public ICIICommand\r
+{\r
+public:\r
+       MiscellaneousCommand(CIIProtocolStrategy* pPS) : pCIIStrategy_(pPS), state_(-1), layer_(0)\r
+       {}\r
+\r
+       virtual int GetMinimumParameters() {\r
+               return 5;\r
+       }\r
+\r
+       virtual void Setup(const std::vector<std::wstring>& parameters);\r
+       virtual void Execute();\r
+\r
+private:\r
+       std::wstring filename_;\r
+       std::wstring xmlData_;\r
+       int state_;\r
+       int layer_;\r
+\r
+       CIIProtocolStrategy* pCIIStrategy_;\r
+};\r
+\r
+class ImagestoreCommand : public ICIICommand\r
+{\r
+public:\r
+       ImagestoreCommand(CIIProtocolStrategy* pPS) : pCIIStrategy_(pPS)\r
+       {}\r
+\r
+       virtual int GetMinimumParameters() {\r
+               return 1;\r
+       }\r
+\r
+       virtual void Setup(const std::vector<std::wstring>& parameters);\r
+       virtual void Execute();\r
+\r
+private:\r
+       std::wstring titleName_;\r
+\r
+       CIIProtocolStrategy* pCIIStrategy_;\r
+};\r
+\r
+class KeydataCommand : public ICIICommand\r
+{\r
+public:\r
+       KeydataCommand(CIIProtocolStrategy* pPS) : pCIIStrategy_(pPS), state_(-1), layer_(0)\r
+       {}\r
+\r
+       virtual int GetMinimumParameters() {\r
+               return 1;\r
+       }\r
+\r
+       virtual void Setup(const std::vector<std::wstring>& parameters);\r
+       virtual void Execute();\r
+\r
+private:\r
+       std::wstring titleName_;\r
+       int state_;\r
+       int layer_;\r
+\r
+       CIIProtocolStrategy* pCIIStrategy_;\r
+};\r
+\r
+}      //namespace cii\r
+}}     //namespace caspar
\ No newline at end of file
diff --git a/protocol/cii/CIIProtocolStrategy.cpp b/protocol/cii/CIIProtocolStrategy.cpp
new file mode 100644 (file)
index 0000000..9e6769d
--- /dev/null
@@ -0,0 +1,279 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#include "../StdAfx.h"\r
+\r
+#include <string>\r
+#include <sstream>\r
+#include <algorithm>\r
+#include "CIIProtocolStrategy.h"\r
+#include "CIICommandsimpl.h"\r
+#include <modules/flash/producer/flash_producer.h>\r
+#include <core/producer/transition/transition_producer.h>\r
+#include <core/mixer/mixer.h>\r
+#include <common/env.h>\r
+\r
+#include <boost/algorithm/string/replace.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
+#endif\r
+\r
+namespace caspar { namespace protocol { namespace cii {\r
+       \r
+using namespace core;\r
+\r
+const std::wstring CIIProtocolStrategy::MessageDelimiter = TEXT("\r\n");\r
+const TCHAR CIIProtocolStrategy::TokenDelimiter = TEXT('\\');\r
+\r
+CIIProtocolStrategy::CIIProtocolStrategy(const std::vector<safe_ptr<core::video_channel>>& channels) : pChannel_(channels.at(0)), executor_(L"CIIProtocolStrategy")\r
+{\r
+}\r
+\r
+void CIIProtocolStrategy::Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo) \r
+{\r
+       std::size_t pos;\r
+       std::wstring msg(pData, charCount);\r
+       std::wstring availibleData = currentMessage_ + msg;\r
+\r
+       while(true)\r
+       {\r
+               pos = availibleData.find(MessageDelimiter);\r
+               if(pos != std::wstring::npos)\r
+               {\r
+                       std::wstring message = availibleData.substr(0,pos);\r
+\r
+                       if(message.length() > 0) {\r
+                               ProcessMessage(message, pClientInfo);\r
+                               if(pClientInfo != 0)\r
+                                       pClientInfo->Send(TEXT("*\r\n"));\r
+                       }\r
+\r
+                       std::size_t nextStartPos = pos + MessageDelimiter.length();\r
+                       if(nextStartPos < availibleData.length())\r
+                               availibleData = availibleData.substr(nextStartPos);\r
+                       else \r
+                       {\r
+                               availibleData.clear();\r
+                               break;\r
+                       }\r
+               }\r
+               else\r
+                       break;\r
+       }\r
+       currentMessage_ = availibleData;\r
+}\r
+\r
+void CIIProtocolStrategy::ProcessMessage(const std::wstring& message, IO::ClientInfoPtr pClientInfo)\r
+{      \r
+       CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message << L"\\r\\n";\r
+\r
+       std::vector<std::wstring> tokens;\r
+       int tokenCount = TokenizeMessage(message, &tokens);\r
+\r
+       CIICommandPtr pCommand = Create(tokens[0]);\r
+       if((pCommand != 0) && (tokenCount-1) >= pCommand->GetMinimumParameters()) \r
+       {\r
+               pCommand->Setup(tokens);\r
+               executor_.begin_invoke([=]{pCommand->Execute();});\r
+       }\r
+       else {} //report error  \r
+}\r
+\r
+int CIIProtocolStrategy::TokenizeMessage(const std::wstring& message, std::vector<std::wstring>* pTokenVector)\r
+{\r
+       std::wstringstream currentToken;\r
+\r
+       for(unsigned int charIndex=0; charIndex<message.size(); ++charIndex) \r
+       {\r
+               if(message[charIndex] == TokenDelimiter) \r
+               {\r
+                       pTokenVector->push_back(currentToken.str());\r
+                       currentToken.str(TEXT(""));\r
+                       continue;\r
+               }\r
+\r
+               if(message[charIndex] == TEXT('\"')) \r
+                       currentToken << TEXT("&quot;");         \r
+               else if(message[charIndex] == TEXT('<')) \r
+                       currentToken << TEXT("&lt;");           \r
+               else if(message[charIndex] == TEXT('>')) \r
+                       currentToken << TEXT("&gt;");           \r
+               else \r
+                       currentToken << message[charIndex];\r
+       }\r
+\r
+       if(currentToken.str().size() > 0)\r
+               pTokenVector->push_back(currentToken.str());    \r
+\r
+       return (int)pTokenVector->size();\r
+}\r
+\r
+/************\r
+// Examples (<X> = ASCIICHAR X)\r
+\r
+I\25\3\VII\\                                                                   sätter outputtype till 'vii'\r
+I\25\4\1\\                                                                             enablar framebuffer (ignore this)\r
+\r
+M\C/SVTNEWS\\                                                                  pekar ut vilken grafisk profil som skall användas\r
+\r
+W\4009\4067\Jonas Björkman\\                                   Skriver "Jonas Björkman" till första textfältet i template 4067 och sparar den färdiga skylten som 4009\r
+\r
+T\7\4009.VII\A\\                                                               lägger ut skylt 4009\r
+\r
+Y\<205><247><202><196><192><192><200><248>\\   lägger ut skylten 4008 (<205><247><202><196><192><192><200><248> = "=g:4008h" om man drar bort 144 från varje asciivärde)\r
+\r
+V\5\3\1\1\namn.tga\1\\                                                 lägger ut bilden namn.tga\r
+V\0\1\D\C\10\0\0\0\\                                                   gör någon inställning som har med föregående kommando att göra.\r
+\r
+*************/\r
+\r
+/**********************\r
+New Commands to support the Netupe automation system\r
+V\5\13\1\1\Template\0\TabField1\TabField2...\\         Build. Ettan före Template indikerar vilket lager den nya templaten skall laddas in i. OBS. Skall inte visas efter det här steget\r
+Y\<27>\\                                                                                       Stop. Här kommer ett lagerID också att skickas med (<27> = ESC)\r
+Y\<254>\\                                                                                      Clear Canvas. Här kommer ett lagerID också att skickas med, utan det skall allt tömmas\r
+Y\<213><243>\\                                                                         Play. Här kommer ett lagerID också att skickas med\r
+\r
+**********************/\r
+CIICommandPtr CIIProtocolStrategy::Create(const std::wstring& name)\r
+{\r
+       switch(name[0])\r
+       {\r
+               case TEXT('M'): return std::make_shared<MediaCommand>(this);\r
+               case TEXT('W'): return std::make_shared<WriteCommand>(this);\r
+               case TEXT('T'): return std::make_shared<ImagestoreCommand>(this);\r
+               case TEXT('V'): return std::make_shared<MiscellaneousCommand>(this);\r
+               case TEXT('Y'): return std::make_shared<KeydataCommand>(this);\r
+               default:                return nullptr;\r
+       }\r
+}\r
+\r
+void CIIProtocolStrategy::WriteTemplateData(const std::wstring& templateName, const std::wstring& titleName, const std::wstring& xmlData) \r
+{\r
+       std::wstring fullTemplateFilename = env::template_folder();\r
+       if(currentProfile_.size() > 0)\r
+       {\r
+               fullTemplateFilename += currentProfile_;\r
+               fullTemplateFilename += TEXT("\\");\r
+       }\r
+       fullTemplateFilename += templateName;\r
+       fullTemplateFilename = flash::find_template(fullTemplateFilename);\r
+       if(fullTemplateFilename.empty())\r
+       {\r
+               CASPAR_LOG(error) << "Failed to save instance of " << templateName << TEXT(" as ") << titleName << TEXT(", template ") << fullTemplateFilename << " not found";\r
+               return;\r
+       }\r
+       \r
+       auto producer = flash::create_producer(this->GetChannel()->mixer(), boost::assign::list_of(env::template_folder()+TEXT("CG.fth")));\r
+\r
+       std::wstringstream flashParam;\r
+       flashParam << TEXT("<invoke name=\"Add\" returntype=\"xml\"><arguments><number>1</number><string>") << currentProfile_ << '/' <<  templateName << TEXT("</string><number>0</number><true/><string> </string><string><![CDATA[ ") << xmlData << TEXT(" ]]></string></arguments></invoke>");\r
+       producer->call(flashParam.str());\r
+\r
+       CASPAR_LOG(info) << "Saved an instance of " << templateName << TEXT(" as ") << titleName ;\r
+\r
+       PutPreparedTemplate(titleName, safe_ptr<core::frame_producer>(std::move(producer)));\r
+       \r
+}\r
+\r
+void CIIProtocolStrategy::DisplayTemplate(const std::wstring& titleName)\r
+{\r
+       try\r
+       {\r
+               pChannel_->stage()->load(0, GetPreparedTemplate(titleName));\r
+               pChannel_->stage()->play(0);\r
+\r
+               CASPAR_LOG(info) << L"Displayed title " << titleName ;\r
+       }\r
+       catch(caspar_exception&)\r
+       {\r
+               CASPAR_LOG(error) << L"Failed to display title " << titleName;\r
+       }\r
+}\r
+\r
+void CIIProtocolStrategy::DisplayMediaFile(const std::wstring& filename) \r
+{\r
+       transition_info transition;\r
+       transition.type = transition::mix;\r
+       transition.duration = 12;\r
+\r
+       auto pFP = create_producer(GetChannel()->mixer(), filename);\r
+       auto pTransition = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transition);\r
+\r
+       try\r
+       {\r
+               pChannel_->stage()->load(0, pTransition);\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               CASPAR_LOG(error) << L"Failed to display " << filename ;\r
+               return;\r
+       }\r
+\r
+       pChannel_->stage()->play(0);\r
+\r
+       CASPAR_LOG(info) << L"Displayed " << filename;\r
+}\r
+\r
+safe_ptr<core::frame_producer> CIIProtocolStrategy::GetPreparedTemplate(const std::wstring& titleName)\r
+{\r
+       safe_ptr<core::frame_producer> result(frame_producer::empty());\r
+\r
+       TitleList::iterator it = std::find(titles_.begin(), titles_.end(), titleName);\r
+       if(it != titles_.end()) {\r
+               CASPAR_LOG(debug) << L"Found title with name " << it->titleName;\r
+               result = (*it).pframe_producer;\r
+       }\r
+       else \r
+               CASPAR_LOG(error) << L"Could not find title with name " << titleName;\r
+\r
+       return result;\r
+}\r
+\r
+void CIIProtocolStrategy::PutPreparedTemplate(const std::wstring& titleName, safe_ptr<core::frame_producer>& pFP)\r
+{\r
+       CASPAR_LOG(debug) << L"Saved title with name " << titleName;\r
+\r
+       TitleList::iterator it = std::find(titles_.begin(), titles_.end(), titleName);\r
+       if(it != titles_.end()) {\r
+               titles_.remove((*it));\r
+       }\r
+\r
+       titles_.push_front(TitleHolder(titleName, pFP));\r
+\r
+       if(titles_.size() >= 6)\r
+               titles_.resize(5);\r
+}\r
+\r
+bool operator==(const CIIProtocolStrategy::TitleHolder& lhs, const std::wstring& rhs) \r
+{\r
+       return lhs.titleName == rhs;\r
+}\r
+\r
+bool operator==(const std::wstring& lhs, const CIIProtocolStrategy::TitleHolder& rhs)\r
+{\r
+       return lhs == rhs.titleName;\r
+}\r
+\r
+}}}\r
diff --git a/protocol/cii/CIIProtocolStrategy.h b/protocol/cii/CIIProtocolStrategy.h
new file mode 100644 (file)
index 0000000..88a3b6f
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#pragma once\r
+\r
+#include <core/video_channel.h>\r
+\r
+#include "../util/ProtocolStrategy.h"\r
+#include "CIICommand.h"\r
+\r
+#include <core/producer/stage.h>\r
+\r
+#include <common/concurrency/executor.h>\r
+\r
+namespace caspar { namespace protocol { namespace cii {\r
+\r
+class CIIProtocolStrategy : public IO::IProtocolStrategy\r
+{\r
+public:\r
+       CIIProtocolStrategy(const std::vector<safe_ptr<core::video_channel>>& channels);\r
+\r
+       void Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo);\r
+       UINT GetCodepage() {return 28591;}      //ISO 8859-1\r
+\r
+       void SetProfile(const std::wstring& profile) {currentProfile_ = profile;}\r
+\r
+       safe_ptr<core::video_channel> GetChannel() const{return this->pChannel_;}\r
+\r
+       void DisplayMediaFile(const std::wstring& filename);\r
+       void DisplayTemplate(const std::wstring& titleName);\r
+       void WriteTemplateData(const std::wstring& templateName, const std::wstring& titleName, const std::wstring& xmlData);\r
+\r
+public:\r
+       struct TitleHolder\r
+       {\r
+               TitleHolder() : titleName(TEXT("")), pframe_producer(core::frame_producer::empty())     {}\r
+               TitleHolder(const std::wstring& name, safe_ptr<core::frame_producer> pFP) : titleName(name), pframe_producer(pFP) {}\r
+               TitleHolder(const TitleHolder& th) : titleName(th.titleName), pframe_producer(th.pframe_producer) {}\r
+               const TitleHolder& operator=(const TitleHolder& th) \r
+               {\r
+                       titleName = th.titleName;\r
+                       pframe_producer = th.pframe_producer;\r
+               }\r
+               bool operator==(const TitleHolder& rhs) \r
+               {\r
+                       return pframe_producer == rhs.pframe_producer;\r
+               }\r
+\r
+               std::wstring titleName;\r
+               safe_ptr<core::frame_producer> pframe_producer;\r
+               friend CIIProtocolStrategy;\r
+       };\r
+private:\r
+\r
+       typedef std::list<TitleHolder> TitleList;\r
+       TitleList titles_;\r
+       safe_ptr<core::frame_producer> GetPreparedTemplate(const std::wstring& name);\r
+       void PutPreparedTemplate(const std::wstring& name, safe_ptr<core::frame_producer>& pframe_producer);\r
+\r
+       static const TCHAR TokenDelimiter;\r
+       static const std::wstring MessageDelimiter;\r
+\r
+       void ProcessMessage(const std::wstring& message, IO::ClientInfoPtr pClientInfo);\r
+       int TokenizeMessage(const std::wstring& message, std::vector<std::wstring>* pTokenVector);\r
+       CIICommandPtr Create(const std::wstring& name);\r
+\r
+       executor executor_;\r
+       std::wstring currentMessage_;\r
+\r
+       std::wstring currentProfile_;\r
+       safe_ptr<core::video_channel> pChannel_;\r
+};\r
+\r
+}}}
\ No newline at end of file
diff --git a/protocol/clk/CLKProtocolStrategy.cpp b/protocol/clk/CLKProtocolStrategy.cpp
new file mode 100644 (file)
index 0000000..dda7431
--- /dev/null
@@ -0,0 +1,129 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#include "..\stdafx.h"\r
+\r
+#include "CLKProtocolStrategy.h"\r
+#include "clk_commands.h"\r
+\r
+#include <modules/flash/producer/cg_producer.h>\r
+\r
+#include <string>\r
+#include <algorithm>\r
+#include <locale>\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+       \r
+CLKProtocolStrategy::CLKProtocolStrategy(\r
+       const std::vector<safe_ptr<core::video_channel>>& channels) \r
+       : currentState_(ExpectingNewCommand)\r
+{\r
+       add_command_handlers(command_processor_, channels.at(0));\r
+}\r
+\r
+void CLKProtocolStrategy::reset()\r
+{\r
+       currentState_ = ExpectingNewCommand;\r
+       currentCommandString_.str(L"");\r
+       command_name_.clear();\r
+       parameters_.clear();\r
+}\r
+\r
+void CLKProtocolStrategy::Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo) \r
+{\r
+       for (int index = 0; index < charCount; ++index) \r
+       {\r
+               TCHAR currentByte = pData[index];\r
+               \r
+               if (currentByte < 32)\r
+                       currentCommandString_ << L"<" << static_cast<int>(currentByte) << L">";\r
+               else\r
+                       currentCommandString_ << currentByte;\r
+\r
+               if (currentByte != 0)\r
+               {\r
+                       switch (currentState_)\r
+                       {\r
+                               case ExpectingNewCommand:\r
+                                       if (currentByte == 1) \r
+                                               currentState_ = ExpectingCommand;\r
+                                       //just throw anything else away\r
+                                       break;\r
+                               case ExpectingCommand:\r
+                                       if (currentByte == 2) \r
+                                               currentState_ = ExpectingParameter;\r
+                                       else\r
+                                               command_name_ += currentByte;\r
+                                       break;\r
+                               case ExpectingParameter:\r
+                                       //allocate new parameter\r
+                                       if (parameters_.size() == 0 || currentByte == 2)\r
+                                               parameters_.push_back(std::wstring());\r
+\r
+                                       if (currentByte != 2)\r
+                                       {\r
+                                               //add the character to end end of the last parameter\r
+                                               if (currentByte == L'<')\r
+                                                       parameters_.back() += L"&lt;";\r
+                                               else if (currentByte == L'>')\r
+                                                       parameters_.back() += L"&gt;";\r
+                                               else if (currentByte == L'\"')\r
+                                                       parameters_.back() += L"&quot;";\r
+                                               else\r
+                                                       parameters_.back() += currentByte;\r
+                                       }\r
+\r
+                                       break;\r
+                       }\r
+               }\r
+               else \r
+               {\r
+                       std::transform(\r
+                               command_name_.begin(), command_name_.end(), \r
+                               command_name_.begin(), \r
+                               toupper);\r
+\r
+                       try\r
+                       {\r
+                               if (!command_processor_.handle(command_name_, parameters_))\r
+                               {\r
+                                       CASPAR_LOG(error) << "CLK: Unknown command: " << command_name_;\r
+                               }\r
+                               else\r
+                               {\r
+                                       CASPAR_LOG(debug) << L"CLK: Executed valid command: " \r
+                                               << currentCommandString_.str();\r
+                               }\r
+                       } \r
+                       catch (...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(error) << "CLK: Failed to interpret command: " \r
+                                       << currentCommandString_.str();\r
+                       }\r
+\r
+                       reset();\r
+               }\r
+       }\r
+}\r
+\r
+}}}\r
diff --git a/protocol/clk/CLKProtocolStrategy.h b/protocol/clk/CLKProtocolStrategy.h
new file mode 100644 (file)
index 0000000..a2b8ab5
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+#pragma once\r
+\r
+#include <vector>\r
+#include <string>\r
+#include <sstream>\r
+\r
+#include <core/video_channel.h>\r
+\r
+#include "clk_command_processor.h"\r
+#include "../util/ProtocolStrategy.h"\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+\r
+/**\r
+ * Can only handle one connection at a time safely, therefore it should be\r
+ * wrapped in a stateful_protocol_strategy_wrapper.\r
+ */\r
+class CLKProtocolStrategy : public IO::IProtocolStrategy\r
+{\r
+public:\r
+       CLKProtocolStrategy(const std::vector<safe_ptr<core::video_channel>>& channels);\r
+\r
+       void Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo);\r
+       UINT GetCodepage() { return 28591; }    //ISO 8859-1\r
+       \r
+private:\r
+       void reset();\r
+\r
+       enum ParserState\r
+       {\r
+               ExpectingNewCommand,\r
+               ExpectingCommand,\r
+               ExpectingParameter\r
+       };\r
+\r
+       ParserState     currentState_;\r
+       std::wstringstream currentCommandString_;\r
+       std::wstring command_name_;\r
+       std::vector<std::wstring> parameters_;\r
+       clk_command_processor command_processor_;\r
+};\r
+\r
+}}}\r
diff --git a/protocol/clk/clk_command_processor.cpp b/protocol/clk/clk_command_processor.cpp
new file mode 100644 (file)
index 0000000..d614a6a
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "clk_command_processor.h"\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+\r
+clk_command_processor& clk_command_processor::add_handler(\r
+       const std::wstring& command_name, const clk_command_handler& handler)\r
+{\r
+       handlers_.insert(std::make_pair(command_name, handler));\r
+\r
+       return *this;\r
+}\r
+\r
+bool clk_command_processor::handle(\r
+       const std::wstring& command_name, const std::vector<std::wstring>& parameters)\r
+{\r
+       auto handler = handlers_.find(command_name);\r
+\r
+       if (handler == handlers_.end())\r
+               return false;\r
+\r
+       handler->second(parameters);\r
+\r
+       return true;\r
+}\r
+\r
+}}}\r
diff --git a/protocol/clk/clk_command_processor.h b/protocol/clk/clk_command_processor.h
new file mode 100644 (file)
index 0000000..6882cba
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <vector>\r
+#include <string>\r
+#include <map>\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/function.hpp>\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+\r
+typedef boost::function<void (const std::vector<std::wstring>&)> clk_command_handler;\r
+\r
+/**\r
+ * CLK command processor composed by multiple command handlers.\r
+ *\r
+ * Not thread-safe.\r
+ */\r
+class clk_command_processor\r
+{\r
+       std::map<std::wstring, clk_command_handler> handlers_;\r
+public:\r
+       /**\r
+        * Register a handler for a specific command.\r
+        *\r
+        * @param command_name The command name to use this handler for.\r
+        * @param handler      The handler that will handle all commands with the\r
+        *                     specified name.\r
+        *\r
+        * @return this command processor for method chaining.\r
+        */\r
+       clk_command_processor& add_handler(\r
+               const std::wstring& command_name, const clk_command_handler& handler);\r
+\r
+       /**\r
+        * Handle an incoming command.\r
+        *\r
+        * @param command_name The command name.\r
+        * @param parameters   The raw parameters supplied with the command.\r
+        *\r
+        * @return true if the command was handled, false if no handler was\r
+        *         registered to handle the command.\r
+        */\r
+       bool handle(\r
+               const std::wstring& command_name, \r
+               const std::vector<std::wstring>& parameters);\r
+};\r
+\r
+}}}\r
diff --git a/protocol/clk/clk_commands.cpp b/protocol/clk/clk_commands.cpp
new file mode 100644 (file)
index 0000000..502fb78
--- /dev/null
@@ -0,0 +1,182 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include <stdexcept>\r
+#include <sstream>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+#include <common/log/log.h>\r
+\r
+#include <modules/flash/producer/cg_producer.h>\r
+\r
+#include "clk_commands.h"\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+\r
+class command_context\r
+{\r
+       bool clock_loaded_;\r
+       safe_ptr<core::video_channel> channel_;\r
+public:\r
+       command_context(const safe_ptr<core::video_channel>& channel)\r
+               : clock_loaded_(false)\r
+               , channel_(channel)\r
+       {\r
+       }\r
+\r
+       void send_to_flash(const std::wstring& data)\r
+       {\r
+               if (!clock_loaded_) \r
+               {\r
+                       flash::get_default_cg_producer(channel_)->add(\r
+                               0, L"hawrysklocka/clock.ft", true, L"", data);\r
+                       clock_loaded_ = true;\r
+               }\r
+               else\r
+               {\r
+                       flash::get_default_cg_producer(channel_)->update(0, data);\r
+               }\r
+                               \r
+               CASPAR_LOG(debug) << L"CLK: Clockdata sent: " << data;\r
+       }\r
+\r
+       void reset()\r
+       {\r
+               channel_->stage()->clear(flash::cg_producer::DEFAULT_LAYER);\r
+               clock_loaded_ = false;\r
+               CASPAR_LOG(info) << L"CLK: Recieved and executed reset-command";\r
+       }\r
+};\r
+\r
+template<class T>\r
+T require_param(\r
+       std::vector<std::wstring>::const_iterator& params_current,\r
+       const std::vector<std::wstring>::const_iterator& params_end,\r
+       const std::string& param_name)\r
+{\r
+       if (params_current == params_end)\r
+               throw std::runtime_error(param_name + " required");\r
+\r
+       T value = boost::lexical_cast<T>(*params_current);\r
+\r
+       ++params_current;\r
+\r
+       return std::move(value);\r
+}\r
+\r
+std::wstring get_xml(\r
+       const std::wstring& command_name,\r
+       bool has_clock_id,\r
+       bool has_time,\r
+       const std::vector<std::wstring>& parameters)\r
+{\r
+       std::wstringstream stream;\r
+\r
+       stream << L"<templateData>";    \r
+       stream << L"<componentData id=\"command\">";\r
+       stream << L"<command id=\"" << command_name << "\"";\r
+       \r
+       std::vector<std::wstring>::const_iterator it = parameters.begin();\r
+       std::vector<std::wstring>::const_iterator end = parameters.end();\r
+\r
+       if (has_clock_id)\r
+       {\r
+               stream << L" clockID=\""\r
+                       << require_param<int>(it, end, "clock id") << L"\"";\r
+       }\r
+\r
+       if (has_time)\r
+       {\r
+               stream << L" time=\""\r
+                       << require_param<std::wstring>(it, end, "time") << L"\"";\r
+       }\r
+\r
+       bool has_parameters = it != end;\r
+\r
+       stream << (has_parameters ? L">" : L" />");\r
+\r
+       if (has_parameters)\r
+       {\r
+               for (; it != end; ++it)\r
+               {\r
+                       stream << L"<parameter>" << (*it) << L"</parameter>";\r
+               }\r
+\r
+               stream << L"</command>";\r
+       }\r
+\r
+       stream << L"</componentData>";\r
+       stream << L"</templateData>";\r
+\r
+       return stream.str();\r
+}\r
+\r
+clk_command_handler create_send_xml_handler(\r
+       const std::wstring& command_name, \r
+       bool expect_clock, \r
+       bool expect_time, \r
+       const safe_ptr<command_context>& context)\r
+{\r
+       return [=] (const std::vector<std::wstring>& params)\r
+       {\r
+               context->send_to_flash(get_xml(\r
+                       command_name, expect_clock, expect_time, params));\r
+       };\r
+}\r
+\r
+void add_command_handlers(\r
+       clk_command_processor& processor, \r
+       const safe_ptr<core::video_channel>& channel)\r
+{\r
+       auto context = make_safe<command_context>(channel);\r
+\r
+       processor\r
+               .add_handler(L"DUR", \r
+                       create_send_xml_handler(L"DUR", true, true, context))\r
+               .add_handler(L"NEWDUR", \r
+                       create_send_xml_handler(L"NEWDUR", true, true, context))\r
+               .add_handler(L"UNTIL", \r
+                       create_send_xml_handler(L"UNTIL", true, true, context))\r
+               .add_handler(L"NEXTEVENT", \r
+                       create_send_xml_handler(L"NEXTEVENT", true, false, context))\r
+               .add_handler(L"STOP", \r
+                       create_send_xml_handler(L"STOP", true, false, context))\r
+               .add_handler(L"ADD", \r
+                       create_send_xml_handler(L"ADD", true, true, context))\r
+               .add_handler(L"SUB", \r
+                       create_send_xml_handler(L"SUB", true, true, context))\r
+               .add_handler(L"TIMELINE_LOAD", \r
+                       create_send_xml_handler(L"TIMELINE_LOAD", false, false, context))\r
+               .add_handler(L"TIMELINE_PLAY", \r
+                       create_send_xml_handler(L"TIMELINE_PLAY", false, false, context))\r
+               .add_handler(L"TIMELINE_STOP", \r
+                       create_send_xml_handler(L"TIMELINE_STOP", false, false, context))\r
+               .add_handler(L"RESET", [=] (const std::vector<std::wstring>& params)\r
+               {\r
+                       context->reset();\r
+               })\r
+               ;\r
+}\r
+\r
+}}}\r
diff --git a/protocol/clk/clk_commands.h b/protocol/clk/clk_commands.h
new file mode 100644 (file)
index 0000000..af6f1e8
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <core/video_channel.h>\r
+\r
+#include "clk_command_processor.h"\r
+\r
+namespace caspar { namespace protocol { namespace CLK {\r
+\r
+/**\r
+ * Add the CLK command handlers to a command processor.\r
+ *\r
+ * @param processor The command processor to add the command handlers to.\r
+ * @param channel   The channel to play the flash graphics on.\r
+ */\r
+void add_command_handlers(\r
+       clk_command_processor& processor, const safe_ptr<core::video_channel>& channel);\r
+\r
+}}}\r
diff --git a/protocol/protocol.vcxproj b/protocol/protocol.vcxproj
new file mode 100644 (file)
index 0000000..67fb832
--- /dev/null
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\ffmpeg\ffmpeg.vcxproj">\r
+      <Project>{f6223af3-be0b-4b61-8406-98922ce521c2}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\flash\flash.vcxproj">\r
+      <Project>{816deaba-3757-4306-afe0-c27cf96c4dea}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="amcp\AMCPCommand.h" />\r
+    <ClInclude Include="amcp\AMCPCommandQueue.h" />\r
+    <ClInclude Include="amcp\AMCPCommandsImpl.h" />\r
+    <ClInclude Include="amcp\AMCPProtocolStrategy.h" />\r
+    <ClInclude Include="cii\CIICommand.h" />\r
+    <ClInclude Include="cii\CIICommandsImpl.h" />\r
+    <ClInclude Include="cii\CIIProtocolStrategy.h" />\r
+    <ClInclude Include="clk\CLKProtocolStrategy.h" />\r
+    <ClInclude Include="clk\clk_commands.h" />\r
+    <ClInclude Include="clk\clk_command_processor.h" />\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\AsyncEventServer.h" />\r
+    <ClInclude Include="util\ClientInfo.h" />\r
+    <ClInclude Include="util\ProtocolStrategy.h" />\r
+    <ClInclude Include="util\SocketInfo.h" />\r
+    <ClInclude Include="util\stateful_protocol_strategy_wrapper.h" />\r
+    <ClInclude Include="util\Thread.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="amcp\AMCPCommandQueue.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="amcp\AMCPCommandsImpl.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="amcp\AMCPProtocolStrategy.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="cii\CIICommandsImpl.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="cii\CIIProtocolStrategy.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="clk\CLKProtocolStrategy.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="clk\clk_commands.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="clk\clk_command_processor.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Create</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="util\AsyncEventServer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="util\SocketInfo.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="util\stateful_protocol_strategy_wrapper.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="util\Thread.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{2040B361-1FB6-488E-84A5-38A580DA90DE}</ProjectGuid>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <RootNamespace>protocol</RootNamespace>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>true</UseDebugLibraries>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>StaticLibrary</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <IncludePath>../;..\dependencies/tbb/include;..\dependencies\boost;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include;$(IncludePath)</IncludePath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <IncludePath>../;..\dependencies/tbb/include;..\dependencies\boost;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include;$(IncludePath)</IncludePath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <IncludePath>../;..\dependencies/tbb/include;..\dependencies\boost;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include;$(IncludePath)</IncludePath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <IncludePath>../;..\dependencies/tbb/include;..\dependencies\boost;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include;$(IncludePath)</IncludePath>\r
+    <OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>\r
+    <IntDir>$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <ClCompile>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <Optimization>Disabled</Optimization>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_DEBUG;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+    </Link>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <FunctionLevelLinking>true</FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <Lib>\r
+      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\r
+    </Lib>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <FunctionLevelLinking>true</FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <ClCompile>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <PrecompiledHeader>Use</PrecompiledHeader>\r
+      <Optimization>Disabled</Optimization>\r
+      <FunctionLevelLinking>true</FunctionLevelLinking>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+    </ClCompile>\r
+    <Link>\r
+      <SubSystem>Windows</SubSystem>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+      <OptimizeReferences>true</OptimizeReferences>\r
+    </Link>\r
+    <Lib />\r
+  </ItemDefinitionGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/protocol/protocol.vcxproj.filters b/protocol/protocol.vcxproj.filters
new file mode 100644 (file)
index 0000000..9f2e7d2
--- /dev/null
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{3bfec261-0108-4128-80ab-794afa5f2226}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\util">\r
+      <UniqueIdentifier>{ac6eb3ad-c1d7-4bae-a03d-b1fd752a0305}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\clk">\r
+      <UniqueIdentifier>{9ed5b10f-d494-4460-b868-e36357b3e04d}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\cii">\r
+      <UniqueIdentifier>{abb11aa5-fa66-4e76-8ea6-38f01f6e7dff}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\amcp">\r
+      <UniqueIdentifier>{93331f26-581b-4d15-81a6-0aae31ad3958}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="amcp\AMCPCommand.h">\r
+      <Filter>source\amcp</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="amcp\AMCPProtocolStrategy.h">\r
+      <Filter>source\amcp</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="amcp\AMCPCommandQueue.h">\r
+      <Filter>source\amcp</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="amcp\AMCPCommandsImpl.h">\r
+      <Filter>source\amcp</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\AsyncEventServer.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="cii\CIICommand.h">\r
+      <Filter>source\cii</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="cii\CIIProtocolStrategy.h">\r
+      <Filter>source\cii</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="cii\CIICommandsImpl.h">\r
+      <Filter>source\cii</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="clk\CLKProtocolStrategy.h">\r
+      <Filter>source\clk</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\ClientInfo.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\Thread.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\ProtocolStrategy.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\SocketInfo.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="clk\clk_command_processor.h">\r
+      <Filter>source\clk</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="clk\clk_commands.h">\r
+      <Filter>source\clk</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="util\stateful_protocol_strategy_wrapper.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="amcp\AMCPCommandQueue.cpp">\r
+      <Filter>source\amcp</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="amcp\AMCPCommandsImpl.cpp">\r
+      <Filter>source\amcp</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="amcp\AMCPProtocolStrategy.cpp">\r
+      <Filter>source\amcp</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\AsyncEventServer.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="cii\CIICommandsImpl.cpp">\r
+      <Filter>source\cii</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="cii\CIIProtocolStrategy.cpp">\r
+      <Filter>source\cii</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="clk\CLKProtocolStrategy.cpp">\r
+      <Filter>source\clk</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\SocketInfo.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\Thread.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="clk\clk_command_processor.cpp">\r
+      <Filter>source\clk</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="clk\clk_commands.cpp">\r
+      <Filter>source\clk</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="util\stateful_protocol_strategy_wrapper.cpp">\r
+      <Filter>source\util</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/protocol/util/AsyncEventServer.cpp b/protocol/util/AsyncEventServer.cpp
new file mode 100644 (file)
index 0000000..558b472
--- /dev/null
@@ -0,0 +1,616 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+// AsyncEventServer.cpp: implementation of the AsyncEventServer class.\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "AsyncEventServer.h"\r
+#include "SocketInfo.h"\r
+\r
+#include <common/log/log.h>\r
+#include <string>\r
+#include <algorithm>\r
+#include <boost/algorithm/string/replace.hpp>\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (push, 1) // TODO: Legacy code, just disable warnings, will replace with boost::asio in future\r
+#endif\r
+\r
+namespace caspar { namespace IO {\r
+       \r
+#define CASPAR_MAXIMUM_SOCKET_CLIENTS  (MAXIMUM_WAIT_OBJECTS-1)        \r
+\r
+long AsyncEventServer::instanceCount_ = 0;\r
+//////////////////////////////\r
+// AsyncEventServer constructor\r
+// PARAMS: port(TCP-port the server should listen to)\r
+// COMMENT: Initializes the WinSock2 library\r
+AsyncEventServer::AsyncEventServer(const safe_ptr<IProtocolStrategy>& pProtocol, int port) : port_(port), pProtocolStrategy_(pProtocol)\r
+{\r
+       if(instanceCount_ == 0) {\r
+               WSADATA wsaData;\r
+               if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)\r
+                       throw std::exception("Error initializing WinSock2");\r
+               else {\r
+                       CASPAR_LOG(info) << "WinSock2 Initialized.";\r
+               }\r
+       }\r
+\r
+       InterlockedIncrement(&instanceCount_);\r
+}\r
+\r
+/////////////////////////////\r
+// AsyncEventServer destructor\r
+AsyncEventServer::~AsyncEventServer() {\r
+       Stop();\r
+\r
+       InterlockedDecrement(&instanceCount_);\r
+       if(instanceCount_ == 0)\r
+               WSACleanup();\r
+}\r
+\r
+void AsyncEventServer::SetClientDisconnectHandler(ClientDisconnectEvent handler) {\r
+       socketInfoCollection_.onSocketInfoRemoved = handler;\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::Start\r
+// RETURNS: true at successful startup\r
+bool AsyncEventServer::Start() {\r
+       if(listenThread_.IsRunning())\r
+               return false;\r
+\r
+       socketInfoCollection_.Clear();\r
+\r
+       sockaddr_in sockAddr;\r
+       ZeroMemory(&sockAddr, sizeof(sockAddr));\r
+       sockAddr.sin_family = AF_INET;\r
+       sockAddr.sin_addr.s_addr = INADDR_ANY;\r
+       sockAddr.sin_port = htons(port_);\r
+       \r
+       SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
+       if(listenSocket == INVALID_SOCKET) {\r
+               CASPAR_LOG(error) << "Failed to create listenSocket";\r
+               return false;\r
+       }\r
+       \r
+       pListenSocketInfo_ = SocketInfoPtr(new SocketInfo(listenSocket, this));\r
+\r
+       if(WSAEventSelect(pListenSocketInfo_->socket_, pListenSocketInfo_->event_, FD_ACCEPT|FD_CLOSE) == SOCKET_ERROR) {\r
+               CASPAR_LOG(error) << "Failed to enter EventSelect-mode for listenSocket";\r
+               return false;\r
+       }\r
+\r
+       if(bind(pListenSocketInfo_->socket_, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {\r
+               CASPAR_LOG(error) << "Failed to bind listenSocket";\r
+               return false;\r
+       }\r
+\r
+       if(listen(pListenSocketInfo_->socket_, SOMAXCONN) == SOCKET_ERROR) {\r
+               CASPAR_LOG(error) << "Failed to listen";\r
+               return false;\r
+       }\r
+\r
+       socketInfoCollection_.AddSocketInfo(pListenSocketInfo_);\r
+\r
+       //start thread: the entrypoint is Run(EVENT stopEvent)\r
+       if(!listenThread_.Start(this)) {\r
+               CASPAR_LOG(error) << "Failed to create ListenThread";\r
+               return false;\r
+       }\r
+\r
+       CASPAR_LOG(info) << "Listener successfully initialized";\r
+       return true;\r
+}\r
+\r
+void AsyncEventServer::Run(HANDLE stopEvent)\r
+{\r
+       WSANETWORKEVENTS networkEvents;\r
+\r
+       HANDLE waitHandlesCopy[MAXIMUM_WAIT_OBJECTS];\r
+       waitHandlesCopy[0] = stopEvent;\r
+\r
+       while(true)     {\r
+               //Update local copy of the array of wait-handles if nessecery\r
+               if(socketInfoCollection_.IsDirty()) {\r
+                       socketInfoCollection_.CopyCollectionToArray(&(waitHandlesCopy[1]), CASPAR_MAXIMUM_SOCKET_CLIENTS);\r
+                       socketInfoCollection_.ClearDirty();\r
+               }\r
+\r
+               DWORD waitResult = WSAWaitForMultipleEvents(std::min<DWORD>(static_cast<DWORD>(socketInfoCollection_.Size()+1), MAXIMUM_WAIT_OBJECTS), waitHandlesCopy, FALSE, 1500, FALSE);\r
+               if(waitResult == WAIT_TIMEOUT)\r
+                       continue;\r
+               else if(waitResult == WAIT_FAILED)\r
+                       break;\r
+               else {\r
+                       DWORD eventIndex = waitResult - WAIT_OBJECT_0;\r
+\r
+                       HANDLE waitEvent = waitHandlesCopy[eventIndex];\r
+                       SocketInfoPtr pSocketInfo;\r
+\r
+                       if(eventIndex == 0)     //stopEvent\r
+                               break;\r
+                       else if(socketInfoCollection_.FindSocketInfo(waitEvent, pSocketInfo)) {\r
+                               WSAEnumNetworkEvents(pSocketInfo->socket_, waitEvent, &networkEvents);\r
+\r
+                               if(networkEvents.lNetworkEvents & FD_ACCEPT) {\r
+                                       if(networkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)\r
+                                               OnAccept(pSocketInfo);\r
+                                       else {\r
+                                               CASPAR_LOG(debug) << "OnAccept (ErrorCode: " << networkEvents.iErrorCode[FD_ACCEPT_BIT] << TEXT(")");\r
+                                               OnError(waitEvent, networkEvents.iErrorCode[FD_ACCEPT_BIT]);\r
+                                       }\r
+                               }\r
+\r
+                               if(networkEvents.lNetworkEvents & FD_CLOSE) {\r
+                                       if(networkEvents.iErrorCode[FD_CLOSE_BIT] == 0)\r
+                                               OnClose(pSocketInfo);\r
+                                       else {\r
+                                               CASPAR_LOG(debug) << "OnClose (ErrorCode: " << networkEvents.iErrorCode[FD_CLOSE_BIT] << TEXT(")");\r
+                                               OnError(waitEvent, networkEvents.iErrorCode[FD_CLOSE_BIT]);\r
+                                       }\r
+                                       continue;\r
+                               }\r
+\r
+                               if(networkEvents.lNetworkEvents & FD_READ) {\r
+                                       if(networkEvents.iErrorCode[FD_READ_BIT] == 0)\r
+                                               OnRead(pSocketInfo);\r
+                                       else {\r
+                                               CASPAR_LOG(debug) << "OnRead (ErrorCode: " << networkEvents.iErrorCode[FD_READ_BIT] << TEXT(")");\r
+                                               OnError(waitEvent, networkEvents.iErrorCode[FD_READ_BIT]);\r
+                                       }\r
+                               }\r
+\r
+                               if(networkEvents.lNetworkEvents & FD_WRITE) {\r
+                                       if(networkEvents.iErrorCode[FD_WRITE_BIT] == 0)\r
+                                               OnWrite(pSocketInfo);\r
+                                       else {\r
+                                               CASPAR_LOG(debug) << "OnWrite (ErrorCode: " << networkEvents.iErrorCode[FD_WRITE_BIT] << TEXT(")");\r
+                                               OnError(waitEvent, networkEvents.iErrorCode[FD_WRITE_BIT]);\r
+                                       }\r
+                               }\r
+                       }\r
+                       else {\r
+                               //Could not find the waitHandle in the SocketInfoCollection.\r
+                               //It must have been removed during the last call to WSAWaitForMultipleEvents\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+bool AsyncEventServer::OnUnhandledException(const std::exception& ex) throw() {\r
+       bool bDoRestart = true;\r
+\r
+       try \r
+       {\r
+               CASPAR_LOG(fatal) << "UNHANDLED EXCEPTION in TCPServers listeningthread. Message: " << ex.what();\r
+       }\r
+       catch(...)\r
+       {\r
+               bDoRestart = false;\r
+       }\r
+\r
+       return bDoRestart;\r
+}\r
+\r
+///////////////////////////////\r
+// AsyncEventServer:Stop\r
+// COMMENT: Shuts down\r
+void AsyncEventServer::Stop()\r
+{\r
+       //TODO: initiate shutdown on all clients connected\r
+//     for(int i=0; i < _totalActiveSockets; ++i) {\r
+//             shutdown(_pSocketInfo[i]->_socket, SD_SEND);\r
+//     }\r
+\r
+       if(!listenThread_.Stop()) {\r
+               CASPAR_LOG(warning) << "Wait for listenThread timed out.";\r
+       }\r
+\r
+       socketInfoCollection_.Clear();\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// MESSAGE HANDLERS   \r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::OnAccept\r
+// PARAMS: ...\r
+// COMMENT: Called when a new client connects\r
+bool AsyncEventServer::OnAccept(SocketInfoPtr& pSI) {\r
+       sockaddr_in     clientAddr;\r
+       int addrSize = sizeof(clientAddr);\r
+       SOCKET clientSocket = WSAAccept(pSI->socket_, (sockaddr*)&clientAddr, &addrSize, NULL, NULL);\r
+       if(clientSocket == INVALID_SOCKET) {\r
+               LogSocketError(TEXT("Accept"));\r
+               return false;\r
+       }\r
+\r
+       SocketInfoPtr pClientSocket(new SocketInfo(clientSocket, this));\r
+\r
+       try\r
+       { // !!!!!!!!!!!!\r
+               if(socketInfoCollection_.Size() >= 50) \r
+               {\r
+                       HANDLE handle = nullptr;\r
+                       {\r
+                               tbb::mutex::scoped_lock lock(socketInfoCollection_.mutex_);                             \r
+                               handle = *(socketInfoCollection_.waitEvents_.begin()+0);\r
+                               if(handle == pListenSocketInfo_->event_)\r
+                                       handle = *(socketInfoCollection_.waitEvents_.begin()+1);\r
+                       }\r
+                       socketInfoCollection_.RemoveSocketInfo(handle);\r
+                       CASPAR_LOG(error) << " Too many connections. Removed last used connection.";\r
+               }\r
+       }catch(...){}\r
+\r
+       //Determine if we can handle one more client\r
+       if(socketInfoCollection_.Size() >= CASPAR_MAXIMUM_SOCKET_CLIENTS) {\r
+               CASPAR_LOG(error) << "Could not accept ) << too many connections).";\r
+               return true;\r
+       }\r
+\r
+       if(WSAEventSelect(pClientSocket->socket_, pClientSocket->event_, FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) {\r
+               LogSocketError(TEXT("Accept (failed create event for new client)"));\r
+               return false;\r
+       }\r
+\r
+       TCHAR addressBuffer[32];\r
+       MultiByteToWideChar(CP_ACP, 0, inet_ntoa(clientAddr.sin_addr), -1, addressBuffer, 32);\r
+       pClientSocket->host_ = addressBuffer;\r
+\r
+       socketInfoCollection_.AddSocketInfo(pClientSocket);\r
+\r
+       CASPAR_LOG(info) << "Accepted connection from " << pClientSocket->host_.c_str() << " " << socketInfoCollection_.Size();\r
+\r
+       return true;\r
+}\r
+\r
+bool ConvertMultiByteToWideChar(UINT codePage, char* pSource, int sourceLength, std::vector<wchar_t>& wideBuffer, int& countLeftovers)\r
+{\r
+       if(codePage == CP_UTF8) {\r
+               countLeftovers = 0;\r
+               //check from the end of pSource for ev. uncompleted UTF-8 byte sequence\r
+               if(pSource[sourceLength-1] & 0x80) {\r
+                       //The last byte is part of a multibyte sequence. If the sequence is not complete, we need to save the partial sequence\r
+                       int bytesToCheck = std::min(4, sourceLength);   //a sequence contains a maximum of 4 bytes\r
+                       int currentLeftoverIndex = sourceLength-1;\r
+                       for(; bytesToCheck > 0; --bytesToCheck, --currentLeftoverIndex) {\r
+                               ++countLeftovers;\r
+                               if(pSource[currentLeftoverIndex] & 0x80) {\r
+                                       if(pSource[currentLeftoverIndex] & 0x40) { //The two high-bits are set, this is the "header"\r
+                                               int expectedSequenceLength = 2;\r
+                                               if(pSource[currentLeftoverIndex] & 0x20)\r
+                                                       ++expectedSequenceLength;\r
+                                               if(pSource[currentLeftoverIndex] & 0x10)\r
+                                                       ++expectedSequenceLength;\r
+\r
+                                               if(countLeftovers < expectedSequenceLength) {\r
+                                                       //The sequence is incomplete. Leave the leftovers to be interpreted with the next call\r
+                                                       break;\r
+                                               }\r
+                                               //The sequence is complete, there are no leftovers. \r
+                                               //...OR...\r
+                                               //error. Let the conversion-function take the hit.\r
+                                               countLeftovers = 0;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       //error. Let the conversion-function take the hit.\r
+                                       countLeftovers = 0;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if(countLeftovers == 4) {\r
+                               //error. Let the conversion-function take the hit.\r
+                               countLeftovers = 0;\r
+                       }\r
+               }\r
+       }\r
+\r
+       int charsWritten = 0;\r
+       int sourceBytesToProcess = sourceLength-countLeftovers;\r
+       int wideBufferCapacity = MultiByteToWideChar(codePage, 0, pSource, sourceBytesToProcess, NULL, NULL);\r
+       if(wideBufferCapacity > 0) \r
+       {\r
+               wideBuffer.resize(wideBufferCapacity);\r
+               charsWritten = MultiByteToWideChar(codePage, 0, pSource, sourceBytesToProcess, &wideBuffer[0], wideBuffer.size());\r
+       }\r
+       //copy the leftovers to the front of the buffer\r
+       if(countLeftovers > 0) {\r
+               memcpy(pSource, &(pSource[sourceBytesToProcess]), countLeftovers);\r
+       }\r
+\r
+       wideBuffer.resize(charsWritten);\r
+       return (charsWritten > 0);\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::OnRead\r
+// PARAMS: ...\r
+// COMMENT: Called then something arrives on the socket that has to be read\r
+bool AsyncEventServer::OnRead(SocketInfoPtr& pSI) {\r
+       int recvResult = SOCKET_ERROR;\r
+       \r
+       try\r
+       { // !!!!!!!!!!!!\r
+               if(pSI)\r
+               {\r
+                       tbb::mutex::scoped_lock lock(socketInfoCollection_.mutex_);\r
+                       auto it = std::find(socketInfoCollection_.waitEvents_.begin(), socketInfoCollection_.waitEvents_.end(), pSI->event_);\r
+                       if(it != socketInfoCollection_.waitEvents_.end())\r
+                       {\r
+                               auto handle = *it;\r
+                               socketInfoCollection_.waitEvents_.erase(it);\r
+                               socketInfoCollection_.waitEvents_.push_back(handle);\r
+                       }\r
+               }\r
+       }catch(...){}\r
+\r
+       int maxRecvLength = sizeof(pSI->recvBuffer_)-pSI->recvLeftoverOffset_;\r
+       recvResult = recv(pSI->socket_, pSI->recvBuffer_+pSI->recvLeftoverOffset_, maxRecvLength, 0);\r
+       while(recvResult != SOCKET_ERROR) {\r
+               if(recvResult == 0) {\r
+                       CASPAR_LOG(info) << "Client " << pSI->host_.c_str() << TEXT(" disconnected");\r
+\r
+                       socketInfoCollection_.RemoveSocketInfo(pSI);\r
+                       return true;\r
+               }\r
+\r
+               //Convert to widechar\r
+               if(ConvertMultiByteToWideChar(pProtocolStrategy_->GetCodepage(), pSI->recvBuffer_, recvResult + pSI->recvLeftoverOffset_, pSI->wideRecvBuffer_, pSI->recvLeftoverOffset_))              \r
+                       pProtocolStrategy_->Parse(&pSI->wideRecvBuffer_[0], pSI->wideRecvBuffer_.size(), pSI);          \r
+               else                    \r
+                       CASPAR_LOG(error) << "Read from " << pSI->host_.c_str() << TEXT(" failed, could not convert command to UNICODE");\r
+                       \r
+               maxRecvLength = sizeof(pSI->recvBuffer_)-pSI->recvLeftoverOffset_;\r
+               recvResult = recv(pSI->socket_, pSI->recvBuffer_+pSI->recvLeftoverOffset_, maxRecvLength, 0);\r
+       }\r
+                       \r
+       if(recvResult == SOCKET_ERROR) {\r
+               int errorCode = WSAGetLastError();\r
+               if(errorCode == WSAEWOULDBLOCK)\r
+                       return true;\r
+               else {\r
+                       LogSocketError(TEXT("Read"), errorCode);\r
+                       OnError(pSI->event_, errorCode);\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::OnWrite\r
+// PARAMS: ...\r
+// COMMENT: Called when the socket is ready to send more data\r
+void AsyncEventServer::OnWrite(SocketInfoPtr& pSI) {           \r
+       DoSend(*pSI);   \r
+}\r
+\r
+bool ConvertWideCharToMultiByte(UINT codePage, const std::wstring& wideString, std::vector<char>& destBuffer)\r
+{\r
+       int bytesWritten = 0;\r
+       int multibyteBufferCapacity = WideCharToMultiByte(codePage, 0, wideString.c_str(), static_cast<int>(wideString.length()), 0, 0, NULL, NULL);\r
+       if(multibyteBufferCapacity > 0) \r
+       {\r
+               destBuffer.resize(multibyteBufferCapacity);\r
+               bytesWritten = WideCharToMultiByte(codePage, 0, wideString.c_str(), static_cast<int>(wideString.length()), &destBuffer[0], destBuffer.size(), NULL, NULL);\r
+       }\r
+       destBuffer.resize(bytesWritten);\r
+       return (bytesWritten > 0);\r
+}\r
+\r
+void AsyncEventServer::DoSend(SocketInfo& socketInfo) {\r
+       //Locks the socketInfo-object so that no one else tampers with the sendqueue at the same time\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       while(!socketInfo.sendQueue_.empty() || socketInfo.currentlySending_.size() > 0) {\r
+               if(socketInfo.currentlySending_.size() == 0) {\r
+                       //Read the next string in the queue and convert to UTF-8\r
+                       if(!ConvertWideCharToMultiByte(pProtocolStrategy_->GetCodepage(), socketInfo.sendQueue_.front(), socketInfo.currentlySending_))\r
+                       {\r
+                               CASPAR_LOG(error) << "Send to " << socketInfo.host_.c_str() << TEXT(" failed, could not convert response to UTF-8");\r
+                       }\r
+                       socketInfo.currentlySendingOffset_ = 0;\r
+               }\r
+\r
+               if(socketInfo.currentlySending_.size() > 0) {\r
+                       int bytesToSend = static_cast<int>(socketInfo.currentlySending_.size()-socketInfo.currentlySendingOffset_);\r
+                       int sentBytes = send(socketInfo.socket_, &socketInfo.currentlySending_[0] + socketInfo.currentlySendingOffset_, bytesToSend, 0);\r
+                       if(sentBytes == SOCKET_ERROR) {\r
+                               int errorCode = WSAGetLastError();\r
+                               if(errorCode == WSAEWOULDBLOCK) {\r
+                                       CASPAR_LOG(debug) << "Send to " << socketInfo.host_.c_str() << TEXT(" would block, sending later");\r
+                                       break;\r
+                               }\r
+                               else {\r
+                                       LogSocketError(TEXT("Send"), errorCode);\r
+                                       OnError(socketInfo.event_, errorCode);\r
+\r
+                                       socketInfo.currentlySending_.resize(0);\r
+                                       socketInfo.currentlySendingOffset_ = 0;\r
+                                       socketInfo.sendQueue_.pop();\r
+                                       break;\r
+                               }\r
+                       }\r
+                       else {\r
+                               if(sentBytes == bytesToSend) {\r
+                                       \r
+                                       if(sentBytes < 512)\r
+                                       {\r
+                                               boost::replace_all(socketInfo.sendQueue_.front(), L"\n", L"\\n");\r
+                                               boost::replace_all(socketInfo.sendQueue_.front(), L"\r", L"\\r");\r
+                                               CASPAR_LOG(info) << L"Sent message to " << socketInfo.host_.c_str() << L": " << socketInfo.sendQueue_.front().c_str();\r
+                                       }\r
+                                       else\r
+                                               CASPAR_LOG(info) << "Sent more than 512 bytes to " << socketInfo.host_.c_str();\r
+\r
+                                       socketInfo.currentlySending_.resize(0);\r
+                                       socketInfo.currentlySendingOffset_ = 0;\r
+                                       socketInfo.sendQueue_.pop();\r
+                               }\r
+                               else {\r
+                                       socketInfo.currentlySendingOffset_ += sentBytes;\r
+                                       CASPAR_LOG(info) << "Sent partial message to " << socketInfo.host_.c_str();\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+                       socketInfo.sendQueue_.pop();\r
+       }\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::OnClose\r
+// PARAMS: ...\r
+// COMMENT: Called when a client disconnects / is disconnected\r
+void AsyncEventServer::OnClose(SocketInfoPtr& pSI) {\r
+       CASPAR_LOG(info) << "Client " << pSI->host_.c_str() << TEXT(" was disconnected");\r
+\r
+       socketInfoCollection_.RemoveSocketInfo(pSI);\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::OnError\r
+// PARAMS: ...\r
+// COMMENT: Called when an errorcode is recieved\r
+void AsyncEventServer::OnError(HANDLE waitEvent, int errorCode) {\r
+       if(errorCode == WSAENETDOWN || errorCode == WSAECONNABORTED || errorCode == WSAECONNRESET || errorCode == WSAESHUTDOWN || errorCode == WSAETIMEDOUT || errorCode == WSAENOTCONN || errorCode == WSAENETRESET) {\r
+               SocketInfoPtr pSocketInfo;\r
+               if(socketInfoCollection_.FindSocketInfo(waitEvent, pSocketInfo)) {\r
+                       CASPAR_LOG(info) << "Client " << pSocketInfo->host_.c_str() << TEXT(" was disconnected, Errorcode ") << errorCode;\r
+               }\r
+\r
+               socketInfoCollection_.RemoveSocketInfo(waitEvent);\r
+       }\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::DisconnectClient\r
+// PARAMS: ...\r
+// COMMENT: The client is removed from the actual client-list when an FD_CLOSE notification is recieved\r
+void AsyncEventServer::DisconnectClient(SocketInfo& socketInfo) {\r
+       int result = shutdown(socketInfo.socket_, SD_SEND);\r
+       if(result == SOCKET_ERROR)\r
+               OnError(socketInfo.event_, result);\r
+}\r
+\r
+//////////////////////////////\r
+// AsyncEventServer::LogSocketError\r
+void AsyncEventServer::LogSocketError(const TCHAR* pStr, int socketError) {\r
+       if(socketError == 0)\r
+               socketError = WSAGetLastError();\r
+\r
+       CASPAR_LOG(error) << "Failed to " << pStr << TEXT(" Errorcode: ") << socketError;\r
+}\r
+\r
+\r
+//////////////////////////////\r
+//  SocketInfoCollection\r
+//////////////////////////////\r
+\r
+AsyncEventServer::SocketInfoCollection::SocketInfoCollection() : bDirty_(false) {\r
+}\r
+\r
+AsyncEventServer::SocketInfoCollection::~SocketInfoCollection() {\r
+}\r
+\r
+bool AsyncEventServer::SocketInfoCollection::AddSocketInfo(SocketInfoPtr& pSocketInfo) {\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       waitEvents_.resize(waitEvents_.size()+1);\r
+       bool bSuccess = socketInfoMap_.insert(SocketInfoMap::value_type(pSocketInfo->event_, pSocketInfo)).second;\r
+       if(bSuccess) {\r
+               waitEvents_[waitEvents_.size()-1] = pSocketInfo->event_;\r
+               bDirty_ = true;\r
+       }\r
+\r
+       return bSuccess;\r
+}\r
+\r
+void AsyncEventServer::SocketInfoCollection::RemoveSocketInfo(SocketInfoPtr& pSocketInfo) {\r
+       if(pSocketInfo != 0) {\r
+               RemoveSocketInfo(pSocketInfo->event_);\r
+       }\r
+}\r
+void AsyncEventServer::SocketInfoCollection::RemoveSocketInfo(HANDLE waitEvent) {\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       //Find instance\r
+       SocketInfoPtr pSocketInfo;\r
+       SocketInfoMap::iterator it = socketInfoMap_.find(waitEvent);\r
+       SocketInfoMap::iterator end = socketInfoMap_.end();\r
+       if(it != end)\r
+               pSocketInfo = it->second;\r
+\r
+       if(pSocketInfo) {\r
+               pSocketInfo->pServer_ = NULL;\r
+\r
+               socketInfoMap_.erase(waitEvent);\r
+\r
+               HandleVector::iterator it = std::find(waitEvents_.begin(), waitEvents_.end(), waitEvent);\r
+               if(it != waitEvents_.end()) {\r
+                       std::swap((*it), waitEvents_.back());\r
+                       waitEvents_.resize(waitEvents_.size()-1);\r
+\r
+                       bDirty_ = true;\r
+               }\r
+       }\r
+       if(onSocketInfoRemoved)\r
+               onSocketInfoRemoved(pSocketInfo);\r
+}\r
+\r
+bool AsyncEventServer::SocketInfoCollection::FindSocketInfo(HANDLE key, SocketInfoPtr& pResult) {\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       SocketInfoMap::iterator it = socketInfoMap_.find(key);\r
+       SocketInfoMap::iterator end = socketInfoMap_.end();\r
+       if(it != end)\r
+               pResult = it->second;\r
+\r
+       return (it != end);\r
+}\r
+\r
+void AsyncEventServer::SocketInfoCollection::CopyCollectionToArray(HANDLE* pDest, int maxCount) {\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       memcpy(pDest, &(waitEvents_[0]), std::min( maxCount, static_cast<int>(waitEvents_.size()) ) * sizeof(HANDLE) );\r
+}\r
+\r
+void AsyncEventServer::SocketInfoCollection::Clear() {\r
+       tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+       socketInfoMap_.clear();\r
+       waitEvents_.clear();\r
+}\r
+\r
+}      //namespace IO\r
+}      //namespace caspar
\ No newline at end of file
diff --git a/protocol/util/AsyncEventServer.h b/protocol/util/AsyncEventServer.h
new file mode 100644 (file)
index 0000000..27ee8d6
--- /dev/null
@@ -0,0 +1,143 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
\r
+// AsyncEventServer.h: interface for the AsyncServer class.\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#if !defined(AFX_ASYNCEVENTSERVER_H__0BFA29CB_BE4C_46A0_9CAE_E233ED27A8EC__INCLUDED_)\r
+#define AFX_ASYNCEVENTSERVER_H__0BFA29CB_BE4C_46A0_9CAE_E233ED27A8EC__INCLUDED_\r
+\r
+#if _MSC_VER > 1000\r
+#pragma once\r
+#endif\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <string>\r
+#include <map>\r
+#include <vector>\r
+#include <functional>\r
+\r
+#include "..\util\thread.h"\r
+\r
+#include "ProtocolStrategy.h"\r
+\r
+#include <tbb\mutex.h>\r
+\r
+namespace caspar {\r
+namespace IO {\r
+\r
+class SocketInfo;\r
+typedef std::shared_ptr<SocketInfo> SocketInfoPtr;\r
+\r
+typedef std::function<void(caspar::IO::SocketInfoPtr)> ClientDisconnectEvent;\r
+\r
+class AsyncEventServer : public IRunnable\r
+{\r
+       static long instanceCount_;\r
+\r
+       AsyncEventServer();\r
+       AsyncEventServer(const AsyncEventServer&);\r
+       AsyncEventServer& operator=(const AsyncEventServer&);\r
+\r
+public:\r
+       explicit AsyncEventServer(const safe_ptr<IProtocolStrategy>& pProtocol, int port);\r
+       ~AsyncEventServer();\r
+\r
+       bool Start();\r
+       void SetProtocolStrategy(safe_ptr<IProtocolStrategy> pPS) {\r
+               pProtocolStrategy_ = pPS;\r
+       }\r
+\r
+       void Stop();\r
+\r
+       void SetClientDisconnectHandler(ClientDisconnectEvent handler);\r
+       \r
+private:\r
+       Thread  listenThread_;\r
+       void Run(HANDLE stopEvent);\r
+       bool OnUnhandledException(const std::exception&) throw();\r
+\r
+       bool OnAccept(SocketInfoPtr&);\r
+       bool OnRead(SocketInfoPtr&);\r
+       void OnWrite(SocketInfoPtr&);\r
+       void OnClose(SocketInfoPtr&);\r
+       void OnError(HANDLE waitEvent, int errorCode);\r
+\r
+       SocketInfoPtr           pListenSocketInfo_;\r
+       safe_ptr<IProtocolStrategy>     pProtocolStrategy_;\r
+       int                                     port_;\r
+\r
+       friend class SocketInfo;\r
+       void DoSend(SocketInfo&);\r
+       void DisconnectClient(SocketInfo&);\r
+\r
+       void LogSocketError(const TCHAR* pStr, int socketError = 0);\r
+\r
+       class SocketInfoCollection\r
+       {\r
+               SocketInfoCollection(const SocketInfoCollection&);\r
+               SocketInfoCollection& operator=(const SocketInfoCollection&);\r
+\r
+               typedef std::map<HANDLE, SocketInfoPtr> SocketInfoMap;\r
+               typedef std::vector<HANDLE> HandleVector;\r
+\r
+       public:\r
+               SocketInfoCollection();\r
+               ~SocketInfoCollection();\r
+\r
+               bool AddSocketInfo(SocketInfoPtr& pSocketInfo);\r
+               void RemoveSocketInfo(SocketInfoPtr& pSocketInfo);\r
+               void RemoveSocketInfo(HANDLE);\r
+               void CopyCollectionToArray(HANDLE*, int maxCount);\r
+\r
+               bool FindSocketInfo(HANDLE, SocketInfoPtr& pResult);\r
+\r
+               bool IsDirty() {\r
+                       return bDirty_;\r
+               }\r
+               void ClearDirty() {\r
+                       bDirty_ = false;\r
+               }\r
+\r
+               std::size_t Size() {\r
+                       return waitEvents_.size();\r
+               }\r
+               void Clear();\r
+\r
+               ClientDisconnectEvent onSocketInfoRemoved;\r
+               \r
+               HandleVector waitEvents_;\r
+               tbb::mutex mutex_;\r
+       private:\r
+               SocketInfoMap socketInfoMap_;\r
+               bool bDirty_;\r
+       };\r
+       SocketInfoCollection socketInfoCollection_;\r
+       tbb::mutex mutex_;\r
+};\r
+typedef std::tr1::shared_ptr<AsyncEventServer> AsyncEventServerPtr;\r
+\r
+}      //namespace IO\r
+}      //namespace caspar\r
+\r
+#endif // !defined(AFX_ASYNCEVENTSERVER_H__0BFA29CB_BE4C_46A0_9CAE_E233ED27A8EC__INCLUDED_)\r
diff --git a/protocol/util/ClientInfo.h b/protocol/util/ClientInfo.h
new file mode 100644 (file)
index 0000000..77c7e58
--- /dev/null
@@ -0,0 +1,58 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#include <memory>\r
+#include <string>\r
+#include <iostream>\r
+\r
+#include <common/log/log.h>\r
+\r
+namespace caspar { namespace IO {\r
+\r
+class ClientInfo \r
+{\r
+protected:\r
+       ClientInfo(){}\r
+\r
+public:\r
+       virtual ~ClientInfo(){}\r
+\r
+       virtual void Send(const std::wstring& data) = 0;\r
+       virtual void Disconnect() = 0;\r
+       virtual std::wstring print() const = 0;\r
+\r
+       std::wstring            currentMessage_;\r
+};\r
+typedef std::shared_ptr<ClientInfo> ClientInfoPtr;\r
+\r
+struct ConsoleClientInfo : public caspar::IO::ClientInfo \r
+{\r
+       void Send(const std::wstring& data)\r
+       {\r
+               std::wcout << (L"#" + caspar::log::replace_nonprintable_copy(data, L'?'));\r
+       }\r
+       void Disconnect(){}\r
+       virtual std::wstring print() const {return L"Console";}\r
+};\r
+\r
+}}\r
diff --git a/protocol/util/ProtocolStrategy.h b/protocol/util/ProtocolStrategy.h
new file mode 100644 (file)
index 0000000..8c95e97
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+ #pragma once\r
+\r
+#include <string>\r
+#include "ClientInfo.h"\r
+\r
+namespace caspar { namespace IO {\r
+\r
+class IProtocolStrategy\r
+{\r
+public:\r
+       virtual ~IProtocolStrategy(){}\r
+\r
+       virtual void Parse(const wchar_t* pData, int charCount, ClientInfoPtr pClientInfo) = 0;\r
+       virtual unsigned int GetCodepage() = 0;\r
+};\r
+typedef std::shared_ptr<IProtocolStrategy> ProtocolStrategyPtr;\r
+\r
+}}     //namespace caspar
\ No newline at end of file
diff --git a/protocol/util/SocketInfo.cpp b/protocol/util/SocketInfo.cpp
new file mode 100644 (file)
index 0000000..dbc2ca3
--- /dev/null
@@ -0,0 +1,64 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "../stdafx.h"\r
+#include "SocketInfo.h"\r
+#include "AsyncEventServer.h"\r
+\r
+namespace caspar {\r
+namespace IO {\r
+\r
+SocketInfo::SocketInfo(SOCKET socket, AsyncEventServer* pServer) : socket_(socket), pServer_(pServer), recvLeftoverOffset_(0), currentlySendingOffset_(0)\r
+{\r
+       event_ = WSACreateEvent();\r
+       if(event_ == WSA_INVALID_EVENT) {\r
+               throw std::exception("Failed to create WSAEvent");\r
+       }\r
+}\r
+\r
+SocketInfo::~SocketInfo() {\r
+\r
+       WSACloseEvent(event_);\r
+       event_ = 0;\r
+\r
+       closesocket(socket_);\r
+       socket_ = 0;\r
+}\r
+\r
+void SocketInfo::Send(const std::wstring& data) {\r
+       if(pServer_ != 0 && data.length() > 0) {\r
+               {\r
+                       //The lock has to be let go before DoSend is called since that too tries to lock to object\r
+                       tbb::mutex::scoped_lock lock(mutex_);\r
+                       sendQueue_.push(data);\r
+               }\r
+\r
+               pServer_->DoSend(*this);\r
+       }\r
+}\r
+\r
+void SocketInfo::Disconnect() {\r
+       if(pServer_)\r
+               pServer_->DisconnectClient(*this);\r
+}\r
+\r
+}      //namespace IO\r
+}      //namespace caspar
\ No newline at end of file
diff --git a/protocol/util/SocketInfo.h b/protocol/util/SocketInfo.h
new file mode 100644 (file)
index 0000000..0594fe9
--- /dev/null
@@ -0,0 +1,68 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
\r
+#pragma once\r
+\r
+#include "ClientInfo.h"\r
+\r
+#include <tbb\mutex.h>\r
+\r
+#include <winsock2.h>\r
+#include <queue>\r
+#include <vector>\r
+\r
+namespace caspar {\r
+namespace IO {\r
+\r
+class AsyncEventServer;\r
+class SocketInfo : public ClientInfo\r
+{\r
+       SocketInfo(const SocketInfo&);\r
+       SocketInfo& operator=(const SocketInfo&);\r
+\r
+public:\r
+       SocketInfo(SOCKET, AsyncEventServer*);\r
+       virtual ~SocketInfo();\r
+\r
+       void Send(const std::wstring& data);\r
+       void Disconnect();\r
+       virtual std::wstring print() const override {return host_;}\r
+\r
+       SOCKET                  socket_;\r
+       HANDLE                  event_;\r
+       std::wstring    host_;\r
+private:\r
+       tbb::mutex mutex_;\r
+       friend class AsyncEventServer;\r
+       std::queue<std::wstring> sendQueue_;\r
+       AsyncEventServer* pServer_;\r
+\r
+       std::vector<char> currentlySending_;\r
+       unsigned int currentlySendingOffset_;\r
+\r
+       std::vector<wchar_t> wideRecvBuffer_;\r
+       char recvBuffer_[512];\r
+       int recvLeftoverOffset_;\r
+};\r
+typedef std::tr1::shared_ptr<SocketInfo> SocketInfoPtr;\r
+\r
+}      //namespace IO\r
+}      //namespace caspar
\ No newline at end of file
diff --git a/protocol/util/Thread.cpp b/protocol/util/Thread.cpp
new file mode 100644 (file)
index 0000000..1e1099b
--- /dev/null
@@ -0,0 +1,143 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "thread.h"\r
+#include <common/exception/win32_exception.h>\r
+\r
+namespace caspar {\r
+       \r
+Event::Event(bool bManualReset, bool bInitialState) : handle_(0)\r
+{\r
+       handle_ = CreateEvent(0, bManualReset, bInitialState, 0);\r
+       if(handle_ == 0) {\r
+               throw std::exception("Failed to create event");\r
+       }\r
+}\r
+\r
+void Event::Set() {\r
+       SetEvent(handle_);\r
+       // TODO: huh?\r
+       //BOOL res = SetEvent(handle_);\r
+       //if(res == FALSE) {\r
+       //      DWORD error = GetLastError();\r
+       //}\r
+}\r
+void Event::Reset() {\r
+       ResetEvent(handle_);\r
+}\r
+\r
+Event::~Event()\r
+{\r
+       CloseHandle(handle_);\r
+}\r
+\r
+bool Thread::static_bInstallWin32ExceptionHandler_ = true;\r
+\r
+Thread::Thread() : pRunnable_(0), hThread_(0), stopEvent_(TRUE, FALSE), timeout_(10000)  {\r
+}\r
+\r
+Thread::~Thread() {\r
+       Stop();\r
+}\r
+\r
+bool Thread::IsRunning() {\r
+       if(hThread_ != 0) {\r
+               if(WaitForSingleObject(hThread_, 0) == WAIT_OBJECT_0) {\r
+                       CloseHandle(hThread_);\r
+                       hThread_ = 0;\r
+                       pRunnable_ = 0;\r
+               }\r
+       }\r
+\r
+       return (hThread_ != 0);\r
+}\r
+\r
+bool Thread::Start(IRunnable* pRunnable) {\r
+       if(hThread_ == 0) {\r
+               if(pRunnable != 0) {\r
+                       pRunnable_ = pRunnable;\r
+                       stopEvent_.Reset();\r
+                       hThread_ = CreateThread(0, 0, ThreadEntrypoint, this, 0, 0);\r
+\r
+                       if(hThread_ == 0)\r
+                               pRunnable_ = 0;\r
+\r
+                       return (hThread_ != 0);\r
+               }\r
+       }\r
+       return false;\r
+}\r
+\r
+bool Thread::Stop(bool bWait) {\r
+       bool returnValue = true;\r
+\r
+       if(hThread_ != 0) {\r
+               stopEvent_.Set();\r
+\r
+               if(bWait) {\r
+                       DWORD successCode = WaitForSingleObject(hThread_, timeout_);\r
+                       if(successCode != WAIT_OBJECT_0)\r
+                               returnValue = false;\r
+               }\r
+               CloseHandle(hThread_);\r
+\r
+               hThread_ = 0;\r
+               pRunnable_ = 0;\r
+       }\r
+\r
+       return returnValue;\r
+}\r
+\r
+void Thread::EnableWin32ExceptionHandler(bool bEnable) {\r
+       static_bInstallWin32ExceptionHandler_ = bEnable;\r
+}\r
+\r
+DWORD WINAPI Thread::ThreadEntrypoint(LPVOID pParam) {\r
+       Thread* pThis = reinterpret_cast<Thread*>(pParam);\r
+       \r
+       if(Thread::static_bInstallWin32ExceptionHandler_)\r
+               win32_exception::install_handler();\r
+\r
+       _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);\r
+\r
+       pThis->Run();\r
+\r
+       return 0;\r
+}\r
+\r
+void Thread::Run() {\r
+       bool bDoRestart = false;\r
+\r
+       do {\r
+               try {\r
+                       bDoRestart = false;\r
+                       stopEvent_.Reset();\r
+                       pRunnable_->Run(stopEvent_);\r
+               }\r
+               catch(const std::exception& e) {\r
+                       bDoRestart = pRunnable_->OnUnhandledException(e);\r
+               }\r
+       }while(bDoRestart);\r
+}\r
+\r
+}      //namespace caspar
\ No newline at end of file
diff --git a/protocol/util/Thread.h b/protocol/util/Thread.h
new file mode 100644 (file)
index 0000000..92d6e49
--- /dev/null
@@ -0,0 +1,98 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Nicklas P Andersson\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "event.h"\r
+\r
+#include <exception>\r
+#include <memory>\r
+\r
+namespace caspar {\r
+       \r
+class IRunnable\r
+{\r
+public:\r
+       virtual ~IRunnable() {}\r
+       virtual void Run(HANDLE stopEvent) = 0;\r
+       virtual bool OnUnhandledException(const std::exception&) throw() = 0;\r
+};\r
+\r
+class Event\r
+{\r
+public:\r
+       Event(bool bManualReset, bool bInitialState);\r
+       ~Event();\r
+\r
+       operator const HANDLE() const {\r
+               return handle_;\r
+       }\r
+\r
+       HANDLE Handle() const\r
+       {\r
+               return handle_;\r
+       }\r
+\r
+       void Set();\r
+       void Reset();\r
+\r
+private:\r
+       HANDLE handle_;\r
+};\r
+\r
+typedef std::shared_ptr<Event> EventPtr;\r
+\r
+class Thread\r
+{\r
+       Thread(const Thread&);\r
+       Thread& operator=(const Thread&);\r
+public:\r
+       Thread();\r
+       ~Thread();\r
+\r
+       bool Start(IRunnable*);\r
+       bool Stop(bool bWait = true);\r
+\r
+       bool IsRunning();\r
+\r
+       static void EnableWin32ExceptionHandler(bool bEnable);\r
+\r
+       void SetTimeout(DWORD timeout) {\r
+               timeout_ = timeout;\r
+       }\r
+       DWORD GetTimeout() {\r
+               return timeout_;\r
+       }\r
+\r
+private:\r
+       static DWORD WINAPI ThreadEntrypoint(LPVOID pParam);\r
+       void Run();\r
+\r
+       HANDLE                  hThread_;\r
+       IRunnable*              pRunnable_;\r
+\r
+       Event                   stopEvent_;\r
+\r
+       DWORD                   timeout_;\r
+       static bool             static_bInstallWin32ExceptionHandler_;\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/protocol/util/stateful_protocol_strategy_wrapper.cpp b/protocol/util/stateful_protocol_strategy_wrapper.cpp
new file mode 100644 (file)
index 0000000..7c23e00
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#include "../StdAfx.h"\r
+\r
+#include "stateful_protocol_strategy_wrapper.h"\r
+\r
+namespace caspar { namespace IO {\r
+\r
+stateful_protocol_strategy_wrapper::stateful_protocol_strategy_wrapper(\r
+       const std::function<ProtocolStrategyPtr ()>& factory)\r
+       : factory_(factory)\r
+       , codepage_(factory()->GetCodepage())\r
+{\r
+}\r
+\r
+void stateful_protocol_strategy_wrapper::purge_dead_clients()\r
+{\r
+       for (auto it = strategies_.begin(); it != strategies_.end();)\r
+       {\r
+               auto strong = it->first.lock();\r
+\r
+               if (strong)\r
+                       ++it;\r
+               else\r
+                       it = strategies_.erase(it);\r
+       }\r
+}\r
+\r
+void stateful_protocol_strategy_wrapper::Parse(\r
+       const wchar_t* pData, int charCount, ClientInfoPtr pClientInfo)\r
+{\r
+       purge_dead_clients();\r
+\r
+       std::weak_ptr<ClientInfo> weak(pClientInfo);\r
+       ProtocolStrategyPtr strategy;\r
+       auto strategy_iter = strategies_.find(weak);\r
+\r
+       if (strategy_iter == strategies_.end())\r
+       {\r
+               strategy = factory_();\r
+               strategies_.insert(std::make_pair(weak, strategy));\r
+       }\r
+       else\r
+       {\r
+               strategy = strategy_iter->second;\r
+       }\r
+\r
+       strategy->Parse(pData, charCount, pClientInfo);\r
+}\r
+\r
+unsigned int stateful_protocol_strategy_wrapper::GetCodepage()\r
+{\r
+       return codepage_;\r
+}\r
+\r
+}}\r
diff --git a/protocol/util/stateful_protocol_strategy_wrapper.h b/protocol/util/stateful_protocol_strategy_wrapper.h
new file mode 100644 (file)
index 0000000..e6a66d3
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Helge Norberg, helge.norberg@svt.se\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "ProtocolStrategy.h"\r
+\r
+#include <functional>\r
+#include <map>\r
+#include <memory>\r
+\r
+namespace caspar { namespace IO {\r
+\r
+/**\r
+ * A protocol strategy which creates unique protocol strategy instances per\r
+ * client connection, using a supplied factory.\r
+ *\r
+ * This allows for the strategy implementation to only concern about one\r
+ * client.\r
+ */\r
+class stateful_protocol_strategy_wrapper : public IProtocolStrategy\r
+{\r
+       std::function<ProtocolStrategyPtr ()> factory_;\r
+       std::map<\r
+               std::weak_ptr<ClientInfo>, \r
+               ProtocolStrategyPtr, \r
+               std::owner_less<std::weak_ptr<ClientInfo>>> strategies_;\r
+       unsigned int codepage_;\r
+public:\r
+       stateful_protocol_strategy_wrapper(\r
+               const std::function<ProtocolStrategyPtr ()>& factory);\r
+\r
+       virtual void Parse(\r
+               const wchar_t* pData, int charCount, ClientInfoPtr pClientInfo);\r
+\r
+       virtual unsigned int GetCodepage();\r
+private:\r
+       void purge_dead_clients();\r
+};\r
+\r
+}}\r
diff --git a/shell/CasparCG.ico b/shell/CasparCG.ico
new file mode 100644 (file)
index 0000000..ec0f7a9
Binary files /dev/null and b/shell/CasparCG.ico differ
diff --git a/shell/casparcg.config b/shell/casparcg.config
new file mode 100644 (file)
index 0000000..3208e1f
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<configuration>\r
+  <paths>\r
+    <media-path>media\</media-path>\r
+    <log-path>log\</log-path>\r
+    <data-path>data\</data-path>\r
+    <template-path>templates\</template-path>\r
+    <thumbnails-path>thumbnails\</thumbnails-path>\r
+  </paths>\r
+  <channels>\r
+    <channel>\r
+        <video-mode>PAL</video-mode>\r
+        <consumers>\r
+          <screen>\r
+            <device>1</device>\r
+            <windowed>true</windowed>\r
+          </screen>\r
+        </consumers>\r
+    </channel>\r
+  </channels>\r
+  <controllers>\r
+    <tcp>\r
+        <port>5250</port>\r
+        <protocol>AMCP</protocol>\r
+    </tcp>\r
+  </controllers>\r
+</configuration>\r
+\r
+<!--\r
+<log-level>       trace [trace|debug|info|warning|error]</log-level>\r
+<channel-grid>    false [true|false]</channel-grid>\r
+<blend-modes>     false [true|false]</blend-modes>\r
+<auto-deinterlace>true  [true|false]</auto-deinterlace>\r
+<auto-transcode>  true  [true|false]</auto-transcode>\r
+<pipeline-tokens> 2     [1..]       </pipeline-tokens>\r
+<template-hosts>\r
+    <template-host>\r
+        <video-mode/>\r
+        <filename/>\r
+        <width/>\r
+        <height/>\r
+    </template-host>\r
+</template-hosts>\r
+<flash>\r
+    <buffer-depth>auto [auto|1..]</buffer-depth>\r
+</flash>\r
+<thumbnails>\r
+    <generate-thumbnails>true [true|false]</generate-thumbnails>\r
+    <width>256</width>\r
+    <height>144</height>\r
+    <video-grid>2</video-grid>\r
+    <scan-interval-millis>5000</scan-interval-millis>\r
+    <generate-delay-millis>2000</generate-delay-millis>\r
+    <video-mode>720p2500</video-mode>\r
+</thumbnails>\r
+<channels>\r
+    <channel>\r
+        <video-mode> PAL [PAL|NTSC|576p2500|720p2398|720p2400|720p2500|720p5000|720p2997|720p5994|720p3000|720p6000|1080p2398|1080p2400|1080i5000|1080i5994|1080i6000|1080p2500|1080p2997|1080p3000|1080p5000|1080p5994|1080p6000] </video-mode>\r
+        <consumers>\r
+            <decklink>\r
+                <device>[1..]</device>\r
+                <embedded-audio>false [true|false]</embedded-audio>\r
+                <latency>normal [normal|low|default]</latency>\r
+                <keyer>external [external|internal|default]</keyer>\r
+                <key-only>false [true|false]</key-only>\r
+                <buffer-depth>3 [1..]</buffer-depth>\r
+            </decklink> \r
+            <bluefish>\r
+                <device>[1..]</device>\r
+                <embedded-audio>false [true|false]</embedded-audio>\r
+                <key-only>false [true|false]</key-only>\r
+            </bluefish>\r
+            <system-audio></system-audio>\r
+            <screen>\r
+                <device>[0..]</device>\r
+                <aspect-ratio>default [default|4:3|16:9]</aspect-ratio>\r
+                <stretch>fill [none|fill|uniform|uniform_to_fill]</stretch>\r
+                <windowed>false [true|false]</windowed>\r
+                <key-only>false [true|false]</key-only>\r
+                <auto-deinterlace>true [true|false]</auto-deinterlace>\r
+                <vsync>false [true|false]</vsync>\r
+            </screen>\r
+            <file>\r
+                <path></path>\r
+                <vcodec>libx264 [libx264|qtrle]</vcodec>\r
+                <separate-key>false [true|false]</separate-key>\r
+            </file>\r
+        </consumers>\r
+    </channel>\r
+</channels>\r
+-->\r
diff --git a/shell/main.cpp b/shell/main.cpp
new file mode 100644 (file)
index 0000000..a41f385
--- /dev/null
@@ -0,0 +1,383 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+// tbbmalloc_proxy: \r
+// Replace the standard memory allocation routines in Microsoft* C/C++ RTL \r
+// (malloc/free, global new/delete, etc.) with the TBB memory allocator. \r
+\r
+#ifdef _DEBUG\r
+       #define _CRTDBG_MAP_ALLOC\r
+       #include <stdlib.h>\r
+       #include <crtdbg.h>\r
+#else\r
+       #include <tbb/tbbmalloc_proxy.h>\r
+#endif\r
+\r
+#include "resource.h"\r
+\r
+#include "server.h"\r
+\r
+#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
+\r
+#include <locale>\r
+\r
+#include <windows.h>\r
+#include <winnt.h>\r
+#include <mmsystem.h>\r
+#include <atlbase.h>\r
+\r
+#include <protocol/amcp/AMCPProtocolStrategy.h>\r
+\r
+#include <modules/bluefish/bluefish.h>\r
+#include <modules/decklink/decklink.h>\r
+#include <modules/flash/flash.h>\r
+#include <modules/ffmpeg/ffmpeg.h>\r
+#include <modules/image/image.h>\r
+\r
+#include <common/env.h>\r
+#include <common/exception/win32_exception.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/log/log.h>\r
+#include <common/gl/gl_check.h>\r
+#include <common/os/windows/current_version.h>\r
+#include <common/os/windows/system_info.h>\r
+\r
+#include <tbb/task_scheduler_init.h>\r
+#include <tbb/task_scheduler_observer.h>\r
+\r
+#include <boost/property_tree/detail/file_parser_error.hpp>\r
+#include <boost/property_tree/xml_parser.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/thread/future.hpp>\r
+#include <boost/locale.hpp>\r
+#include <boost/algorithm/string/case_conv.hpp>\r
+\r
+// NOTE: This is needed in order to make CComObject work since this is not a real ATL project.\r
+CComModule _AtlModule;\r
+extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;\r
+\r
+void change_icon( const HICON hNewIcon )\r
+{\r
+   auto hMod = ::LoadLibrary(L"Kernel32.dll"); \r
+   typedef DWORD(__stdcall *SCI)(HICON);\r
+   auto pfnSetConsoleIcon = reinterpret_cast<SCI>(::GetProcAddress(hMod, "SetConsoleIcon")); \r
+   pfnSetConsoleIcon(hNewIcon); \r
+   ::FreeLibrary(hMod);\r
+}\r
+\r
+void setup_global_locale()\r
+{\r
+       boost::locale::generator gen;\r
+       gen.categories(boost::locale::codepage_facet);\r
+\r
+       std::locale::global(gen(""));\r
+}\r
+\r
+void setup_console_window()\r
+{       \r
+       auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);\r
+\r
+       // Disable close button in console to avoid shutdown without cleanup.\r
+       EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE , MF_GRAYED);\r
+       DrawMenuBar(GetConsoleWindow());\r
+       //SetConsoleCtrlHandler(HandlerRoutine, true);\r
+\r
+       // Configure console size and position.\r
+       auto coord = GetLargestConsoleWindowSize(hOut);\r
+       coord.X /= 2;\r
+\r
+       SetConsoleScreenBufferSize(hOut, coord);\r
+\r
+       SMALL_RECT DisplayArea = {0, 0, 0, 0};\r
+       DisplayArea.Right = coord.X-1;\r
+       DisplayArea.Bottom = (coord.Y-1)/2;\r
+       SetConsoleWindowInfo(hOut, TRUE, &DisplayArea);\r
+                \r
+       change_icon(::LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(101)));\r
+\r
+       // Set console title.\r
+       std::wstringstream str;\r
+       str << "CasparCG Server " << caspar::env::version();\r
+#ifdef COMPILE_RELEASE\r
+       str << " Release";\r
+#elif  COMPILE_PROFILE\r
+       str << " Profile";\r
+#elif  COMPILE_DEVELOP\r
+       str << " Develop";\r
+#elif  COMPILE_DEBUG\r
+       str << " Debug";\r
+#endif\r
+       SetConsoleTitle(str.str().c_str());\r
+}\r
+\r
+void print_info()\r
+{\r
+       CASPAR_LOG(info) << L"############################################################################";\r
+       CASPAR_LOG(info) << L"CasparCG Server is distributed by the Swedish Broadcasting Corporation (SVT)";\r
+       CASPAR_LOG(info) << L"under the GNU General Public License GPLv3 or higher.";\r
+       CASPAR_LOG(info) << L"Please see LICENSE.TXT for details.";\r
+       CASPAR_LOG(info) << L"http://www.casparcg.com/";\r
+       CASPAR_LOG(info) << L"############################################################################";\r
+       CASPAR_LOG(info) << L"Starting CasparCG Video and Graphics Playout Server " << caspar::env::version();\r
+       CASPAR_LOG(info) << L"on " << caspar::get_win_product_name() << L" " << caspar::get_win_sp_version();\r
+       CASPAR_LOG(info) << caspar::get_cpu_info();\r
+       CASPAR_LOG(info) << caspar::get_system_product_name();\r
+       \r
+       CASPAR_LOG(info) << L"Decklink " << caspar::decklink::get_version();\r
+       BOOST_FOREACH(auto device, caspar::decklink::get_device_list())\r
+               CASPAR_LOG(info) << L" - " << device;   \r
+               \r
+       CASPAR_LOG(info) << L"Bluefish " << caspar::bluefish::get_version();\r
+       BOOST_FOREACH(auto device, caspar::bluefish::get_device_list())\r
+               CASPAR_LOG(info) << L" - " << device;   \r
+       \r
+       CASPAR_LOG(info) << L"FreeImage "               << caspar::image::get_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avcodec "  << caspar::ffmpeg::get_avcodec_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avformat " << caspar::ffmpeg::get_avformat_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avfilter " << caspar::ffmpeg::get_avfilter_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avutil "   << caspar::ffmpeg::get_avutil_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-swscale "  << caspar::ffmpeg::get_swscale_version();\r
+       CASPAR_LOG(info) << L"Flash "                   << caspar::flash::get_version();\r
+       CASPAR_LOG(info) << L"Template-Host "   << caspar::flash::get_cg_version();\r
+}\r
+\r
+LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)\r
+{\r
+       try\r
+       {\r
+               CASPAR_LOG(fatal) << L"#######################\n UNHANDLED EXCEPTION: \n" \r
+                       << L"Adress:" << info->ExceptionRecord->ExceptionAddress << L"\n"\r
+                       << L"Code:" << info->ExceptionRecord->ExceptionCode << L"\n"\r
+                       << L"Flag:" << info->ExceptionRecord->ExceptionFlags << L"\n"\r
+                       << L"Info:" << info->ExceptionRecord->ExceptionInformation << L"\n"\r
+                       << L"Continuing execution. \n#######################";\r
+       }\r
+       catch(...){}\r
+\r
+    return EXCEPTION_EXECUTE_HANDLER;\r
+}\r
+\r
+void make_upper_case(std::wstring& str)\r
+{\r
+       boost::to_upper(str);\r
+}\r
+\r
+int main(int argc, wchar_t* argv[])\r
+{      \r
+       static_assert(sizeof(void*) == 4, "64-bit code generation is not supported.");\r
+       \r
+       SetUnhandledExceptionFilter(UserUnhandledExceptionFilter);\r
+\r
+       setup_global_locale();\r
+\r
+       std::wcout << L"Type \"q\" to close application." << std::endl;\r
+       \r
+       // Set debug mode.\r
+       #ifdef _DEBUG\r
+               HANDLE hLogFile;\r
+               hLogFile = CreateFile(L"crt_log.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\r
+               std::shared_ptr<void> crt_log(nullptr, [](HANDLE h){::CloseHandle(h);});\r
+\r
+               _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);\r
+               _CrtSetReportMode(_CRT_WARN,    _CRTDBG_MODE_FILE);\r
+               _CrtSetReportFile(_CRT_WARN,    hLogFile);\r
+               _CrtSetReportMode(_CRT_ERROR,   _CRTDBG_MODE_FILE);\r
+               _CrtSetReportFile(_CRT_ERROR,   hLogFile);\r
+               _CrtSetReportMode(_CRT_ASSERT,  _CRTDBG_MODE_FILE);\r
+               _CrtSetReportFile(_CRT_ASSERT,  hLogFile);\r
+       #endif\r
+\r
+       // Increase process priotity.\r
+       SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);\r
+\r
+       // Install structured exception handler.\r
+       caspar::win32_exception::install_handler();\r
+                               \r
+       // Increase time precision. This will increase accuracy of function like Sleep(1) from 10 ms to 1 ms.\r
+       struct inc_prec\r
+       {\r
+               inc_prec(){timeBeginPeriod(1);}\r
+               ~inc_prec(){timeEndPeriod(1);}\r
+       } inc_prec;     \r
+\r
+       // Install unstructured exception handlers into all tbb threads.\r
+       struct tbb_thread_installer : public tbb::task_scheduler_observer\r
+       {\r
+               tbb_thread_installer(){observe(true);}\r
+               void on_scheduler_entry(bool is_worker)\r
+               {\r
+                       //caspar::detail::SetThreadName(GetCurrentThreadId(), "tbb-worker-thread");\r
+                       caspar::win32_exception::install_handler();\r
+               }\r
+       } tbb_thread_installer;\r
+\r
+       tbb::task_scheduler_init init;\r
+       \r
+       try \r
+       {\r
+               // Configure environment properties from configuration.\r
+               caspar::env::configure(L"casparcg.config");\r
+                               \r
+               caspar::log::set_log_level(caspar::env::properties().get(L"configuration.log-level", L"debug"));\r
+\r
+       #ifdef _DEBUG\r
+               if(caspar::env::properties().get(L"configuration.debugging.remote", false))\r
+                       MessageBox(nullptr, TEXT("Now is the time to connect for remote debugging..."), TEXT("Debug"), MB_OK | MB_TOPMOST);\r
+       #endif   \r
+\r
+               // Start logging to file.\r
+               caspar::log::add_file_sink(caspar::env::log_folder());                  \r
+               std::wcout << L"Logging [info] or higher severity to " << caspar::env::log_folder() << std::endl << std::endl;\r
+               \r
+               // Setup console window.\r
+               setup_console_window();\r
+\r
+               // Print environment information.\r
+               print_info();\r
+                       \r
+               std::wstringstream str;\r
+               boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);\r
+               boost::property_tree::write_xml(str, caspar::env::properties(), w);\r
+               CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------";\r
+               bool wait_for_keypress;\r
+\r
+               {\r
+                       boost::promise<bool> shutdown_server_now;\r
+                       boost::unique_future<bool> shutdown_server = shutdown_server_now.get_future();\r
+\r
+                       // Create server object which initializes channels, protocols and controllers.\r
+                       caspar::server caspar_server(shutdown_server_now);\r
+\r
+                       // Use separate thread for the blocking console input, will be terminated \r
+                       // anyway when the main thread terminates.\r
+                       boost::thread stdin_thread([&caspar_server, &shutdown_server_now]\r
+                       {\r
+                               // Create a amcp parser for console commands.\r
+                               caspar::protocol::amcp::AMCPProtocolStrategy amcp(\r
+                                               caspar_server.get_channels(),\r
+                                               caspar_server.get_thumbnail_generator(),\r
+                                               shutdown_server_now);\r
+\r
+                               // Create a dummy client which prints amcp responses to console.\r
+                               auto console_client = std::make_shared<caspar::IO::ConsoleClientInfo>();\r
+                               std::wstring wcmd;\r
+       \r
+                               while(true)\r
+                               {\r
+                                       std::getline(std::wcin, wcmd); // TODO: It's blocking...\r
+                               \r
+                                       //boost::to_upper(wcmd);  // TODO COMPILER crashes on this line, Strange!\r
+                                       make_upper_case(wcmd);\r
+\r
+                                       if(wcmd == L"EXIT" || wcmd == L"Q" || wcmd == L"QUIT" || wcmd == L"BYE")\r
+                                       {\r
+                                               shutdown_server_now.set_value(true); // True to wait for keypress\r
+                                               break;\r
+                                       }\r
+                               \r
+                                       try\r
+                                       {\r
+                                               // This is just dummy code for testing.\r
+                                               if(wcmd.substr(0, 1) == L"1")\r
+                                                       wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" SLIDE 100 LOOP \r\nPLAY 1-1";\r
+                                               else if(wcmd.substr(0, 1) == L"2")\r
+                                                       wcmd = L"MIXER 1-0 VIDEO IS_KEY 1";\r
+                                               else if(wcmd.substr(0, 1) == L"3")\r
+                                                       wcmd = L"CG 1-2 ADD 1 BBTELEFONARE 1";\r
+                                               else if(wcmd.substr(0, 1) == L"4")\r
+                                                       wcmd = L"PLAY 1-1 DV FILTER yadif=1:-1 LOOP";\r
+                                               else if(wcmd.substr(0, 1) == L"5")\r
+                                               {\r
+                                                       auto file = wcmd.substr(2, wcmd.length()-1);\r
+                                                       wcmd = L"PLAY 1-1 " + file + L" LOOP\r\n" \r
+                                                                       L"PLAY 1-2 " + file + L" LOOP\r\n" \r
+                                                                       L"PLAY 1-3 " + file + L" LOOP\r\n"\r
+                                                                       L"PLAY 2-1 " + file + L" LOOP\r\n" \r
+                                                                       L"PLAY 2-2 " + file + L" LOOP\r\n" \r
+                                                                       L"PLAY 2-3 " + file + L" LOOP\r\n";\r
+                                               }\r
+                                               else if(wcmd.substr(0, 1) == L"X")\r
+                                               {\r
+                                                       int num = 0;\r
+                                                       std::wstring file;\r
+                                                       try\r
+                                                       {\r
+                                                               num = boost::lexical_cast<int>(wcmd.substr(1, 2));\r
+                                                               file = wcmd.substr(4, wcmd.length()-1);\r
+                                                       }\r
+                                                       catch(...)\r
+                                                       {\r
+                                                               num = boost::lexical_cast<int>(wcmd.substr(1, 1));\r
+                                                               file = wcmd.substr(3, wcmd.length()-1);\r
+                                                       }\r
+\r
+                                                       int n = 0;\r
+                                                       int num2 = num;\r
+                                                       while(num2 > 0)\r
+                                                       {\r
+                                                               num2 >>= 1;\r
+                                                               n++;\r
+                                                       }\r
+\r
+                                                       wcmd = L"MIXER 1 GRID " + boost::lexical_cast<std::wstring>(n);\r
+\r
+                                                       for(int i = 1; i <= num; ++i)\r
+                                                               wcmd += L"\r\nPLAY 1-" + boost::lexical_cast<std::wstring>(i) + L" " + file + L" LOOP";// + L" SLIDE 100 LOOP";\r
+                                               }\r
+                                       }\r
+                                       catch (...)\r
+                                       {\r
+                                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                               continue;\r
+                                       }\r
+\r
+                                       wcmd += L"\r\n";\r
+                                       amcp.Parse(wcmd.c_str(), wcmd.length(), console_client);\r
+                               }       \r
+                       });\r
+                       stdin_thread.detach();\r
+                       wait_for_keypress = shutdown_server.get();\r
+               }\r
+               Sleep(500);\r
+               CASPAR_LOG(info) << "Successfully shutdown CasparCG Server.";\r
+\r
+               if (wait_for_keypress)\r
+                       system("pause");        \r
+       }\r
+       catch(boost::property_tree::file_parser_error&)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               CASPAR_LOG(fatal) << L"Unhandled configuration error in main thread. Please check the configuration file (casparcg.config) for errors.";\r
+               system("pause");        \r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+               CASPAR_LOG(fatal) << L"Unhandled exception in main thread. Please report this error on the CasparCG forums (www.casparcg.com/forum).";\r
+               Sleep(1000);\r
+               std::wcout << L"\n\nCasparCG will automatically shutdown. See the log file located at the configured log-file folder for more information.\n\n";\r
+               Sleep(4000);\r
+       }       \r
+       \r
+       return 0;\r
+}
\ No newline at end of file
diff --git a/shell/resource.h b/shell/resource.h
new file mode 100644 (file)
index 0000000..aebc8e6
Binary files /dev/null and b/shell/resource.h differ
diff --git a/shell/server.cpp b/shell/server.cpp
new file mode 100644 (file)
index 0000000..e36fda8
--- /dev/null
@@ -0,0 +1,240 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+\r
+#include "server.h"\r
+\r
+#include <memory>\r
+\r
+#include <common/env.h>\r
+#include <common/exception/exceptions.h>\r
+#include <common/utility/string.h>\r
+#include <common/filesystem/polling_filesystem_monitor.h>\r
+\r
+#include <core/mixer/gpu/ogl_device.h>\r
+#include <core/video_channel.h>\r
+#include <core/producer/stage.h>\r
+#include <core/consumer/output.h>\r
+#include <core/thumbnail_generator.h>\r
+\r
+#include <modules/bluefish/bluefish.h>\r
+#include <modules/decklink/decklink.h>\r
+#include <modules/ffmpeg/ffmpeg.h>\r
+#include <modules/flash/flash.h>\r
+#include <modules/oal/oal.h>\r
+#include <modules/ogl/ogl.h>\r
+#include <modules/silverlight/silverlight.h>\r
+#include <modules/image/image.h>\r
+#include <modules/image/consumer/image_consumer.h>\r
+\r
+#include <modules/oal/consumer/oal_consumer.h>\r
+#include <modules/bluefish/consumer/bluefish_consumer.h>\r
+#include <modules/decklink/consumer/decklink_consumer.h>\r
+#include <modules/ogl/consumer/ogl_consumer.h>\r
+#include <modules/ffmpeg/consumer/ffmpeg_consumer.h>\r
+\r
+#include <protocol/amcp/AMCPProtocolStrategy.h>\r
+#include <protocol/cii/CIIProtocolStrategy.h>\r
+#include <protocol/CLK/CLKProtocolStrategy.h>\r
+#include <protocol/util/AsyncEventServer.h>\r
+#include <protocol/util/stateful_protocol_strategy_wrapper.h>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/property_tree/xml_parser.hpp>\r
+\r
+namespace caspar {\r
+\r
+using namespace core;\r
+using namespace protocol;\r
+\r
+struct server::implementation : boost::noncopyable\r
+{\r
+       boost::promise<bool>&                                           shutdown_server_now_;\r
+       safe_ptr<ogl_device>                                            ogl_;\r
+       std::vector<safe_ptr<IO::AsyncEventServer>> async_servers_;     \r
+       std::vector<safe_ptr<video_channel>>            channels_;\r
+       std::shared_ptr<thumbnail_generator>            thumbnail_generator_;\r
+\r
+       implementation(boost::promise<bool>& shutdown_server_now)\r
+               : shutdown_server_now_(shutdown_server_now)\r
+               , ogl_(ogl_device::create())\r
+       {                       \r
+               ffmpeg::init();\r
+               CASPAR_LOG(info) << L"Initialized ffmpeg module.";\r
+                                                         \r
+               bluefish::init();         \r
+               CASPAR_LOG(info) << L"Initialized bluefish module.";\r
+                                                         \r
+               decklink::init();         \r
+               CASPAR_LOG(info) << L"Initialized decklink module.";\r
+                                                                                                                 \r
+               oal::init();              \r
+               CASPAR_LOG(info) << L"Initialized oal module.";\r
+                                                         \r
+               ogl::init();              \r
+               CASPAR_LOG(info) << L"Initialized ogl module.";\r
+\r
+               image::init();            \r
+               CASPAR_LOG(info) << L"Initialized image module.";\r
+\r
+               flash::init();            \r
+               CASPAR_LOG(info) << L"Initialized flash module.";\r
+\r
+               setup_channels(env::properties());\r
+               CASPAR_LOG(info) << L"Initialized channels.";\r
+\r
+               setup_thumbnail_generation(env::properties());\r
+\r
+               setup_controllers(env::properties());\r
+               CASPAR_LOG(info) << L"Initialized controllers.";\r
+       }\r
+\r
+       ~implementation()\r
+       {               \r
+               ffmpeg::uninit();\r
+\r
+               async_servers_.clear();\r
+               channels_.clear();\r
+       }\r
+                               \r
+       void setup_channels(const boost::property_tree::wptree& pt)\r
+       {   \r
+               using boost::property_tree::wptree;\r
+               BOOST_FOREACH(auto& xml_channel, pt.get_child(L"configuration.channels"))\r
+               {               \r
+                       auto format_desc = video_format_desc::get(widen(xml_channel.second.get(L"video-mode", L"PAL")));                \r
+                       if(format_desc.format == video_format::invalid)\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid video-mode."));\r
+                       \r
+                       channels_.push_back(make_safe<video_channel>(channels_.size()+1, format_desc, ogl_));\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
+                               {\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               }\r
+                       }                                                       \r
+               }\r
+\r
+               // Dummy diagnostics channel\r
+               if(env::properties().get(L"configuration.channel-grid", false))\r
+                       channels_.push_back(make_safe<video_channel>(channels_.size()+1, core::video_format_desc::get(core::video_format::x576p2500), ogl_));\r
+       }\r
+               \r
+       void setup_controllers(const boost::property_tree::wptree& pt)\r
+       {               \r
+               using boost::property_tree::wptree;\r
+               BOOST_FOREACH(auto& xml_controller, pt.get_child(L"configuration.controllers"))\r
+               {\r
+                       try\r
+                       {\r
+                               auto name = xml_controller.first;\r
+                               auto protocol = xml_controller.second.get<std::wstring>(L"protocol");   \r
+\r
+                               if(name == L"tcp")\r
+                               {                                       \r
+                                       unsigned int port = xml_controller.second.get(L"port", 5250);\r
+                                       auto asyncbootstrapper = make_safe<IO::AsyncEventServer>(create_protocol(protocol), port);\r
+                                       asyncbootstrapper->Start();\r
+                                       async_servers_.push_back(asyncbootstrapper);\r
+                               }\r
+                               else\r
+                                       CASPAR_LOG(warning) << "Invalid controller: " << widen(name);   \r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+               }\r
+       }\r
+\r
+       void setup_thumbnail_generation(const boost::property_tree::wptree& pt)\r
+       {\r
+               if (!pt.get(L"configuration.thumbnails.generate-thumbnails", true))\r
+                       return;\r
+\r
+               auto scan_interval_millis = pt.get(L"configuration.thumbnails.scan-interval-millis", 5000);\r
+\r
+               polling_filesystem_monitor_factory monitor_factory(scan_interval_millis);\r
+               thumbnail_generator_.reset(new thumbnail_generator(\r
+                               monitor_factory, \r
+                               env::media_folder(),\r
+                               env::thumbnails_folder(),\r
+                               pt.get(L"configuration.thumbnails.width", 256),\r
+                               pt.get(L"configuration.thumbnails.height", 144),\r
+                               core::video_format_desc::get(pt.get(L"configuration.thumbnails.video-mode", L"720p2500")),\r
+                               ogl_,\r
+                               pt.get(L"configuration.thumbnails.generate-delay-millis", 2000),\r
+                               &image::write_cropped_png));\r
+\r
+               CASPAR_LOG(info) << L"Initialized thumbnail generator.";\r
+       }\r
+\r
+       safe_ptr<IO::IProtocolStrategy> create_protocol(const std::wstring& name) const\r
+       {\r
+               if(boost::iequals(name, L"AMCP"))\r
+                       return make_safe<amcp::AMCPProtocolStrategy>(channels_, thumbnail_generator_, shutdown_server_now_);\r
+               else if(boost::iequals(name, L"CII"))\r
+                       return make_safe<cii::CIIProtocolStrategy>(channels_);\r
+               else if(boost::iequals(name, L"CLOCK"))\r
+                       //return make_safe<CLK::CLKProtocolStrategy>(channels_);\r
+                       return make_safe<IO::stateful_protocol_strategy_wrapper>([=]\r
+                       {\r
+                               return std::make_shared<CLK::CLKProtocolStrategy>(channels_);\r
+                       });\r
+               \r
+               BOOST_THROW_EXCEPTION(caspar_exception() << arg_name_info("name") << arg_value_info(narrow(name)) << msg_info("Invalid protocol"));\r
+       }\r
+};\r
+\r
+server::server(boost::promise<bool>& shutdown_server_now) : impl_(new implementation(shutdown_server_now)){}\r
+\r
+const std::vector<safe_ptr<video_channel>> server::get_channels() const\r
+{\r
+       return impl_->channels_;\r
+}\r
+\r
+std::shared_ptr<thumbnail_generator> server::get_thumbnail_generator() const\r
+{\r
+       return impl_->thumbnail_generator_;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/shell/server.h b/shell/server.h
new file mode 100644 (file)
index 0000000..13948ee
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
+\r
+#include <vector>\r
+\r
+namespace caspar {\r
+\r
+namespace core {\r
+       class video_channel;\r
+       class thumbnail_generator;\r
+}\r
+\r
+class server : boost::noncopyable\r
+{\r
+public:\r
+       server(boost::promise<bool>& shutdown_server_now);\r
+       const std::vector<safe_ptr<core::video_channel>> get_channels() const;\r
+       std::shared_ptr<core::thumbnail_generator> get_thumbnail_generator() const;\r
+private:\r
+       struct implementation;\r
+       safe_ptr<implementation> impl_;\r
+};\r
+\r
+}
\ No newline at end of file
diff --git a/shell/shell.rc b/shell/shell.rc
new file mode 100644 (file)
index 0000000..7b54f2d
Binary files /dev/null and b/shell/shell.rc differ
diff --git a/shell/shell.vcxproj b/shell/shell.vcxproj
new file mode 100644 (file)
index 0000000..21d8c07
--- /dev/null
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Profile|Win32">\r
+      <Configuration>Profile</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Develop|Win32">\r
+      <Configuration>Develop</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="server.cpp" />\r
+    <ClCompile Include="main.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <ShowIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ShowIncludes>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\common\common.vcxproj">\r
+      <Project>{02308602-7fe0-4253-b96e-22134919f56a}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\core\core.vcxproj">\r
+      <Project>{79388c20-6499-4bf6-b8b9-d8c33d7d4ddd}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\bluefish\bluefish.vcxproj">\r
+      <Project>{69313d25-9f54-4fc9-9872-628a4dd79464}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\decklink\decklink.vcxproj">\r
+      <Project>{d3611658-8f54-43cf-b9af-a5cf8c1102ea}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\ffmpeg\ffmpeg.vcxproj">\r
+      <Project>{f6223af3-be0b-4b61-8406-98922ce521c2}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\flash\flash.vcxproj">\r
+      <Project>{816deaba-3757-4306-afe0-c27cf96c4dea}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\image\image.vcxproj">\r
+      <Project>{3e11ff65-a9da-4f80-87f2-a7c6379ed5e2}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\oal\oal.vcxproj">\r
+      <Project>{82ed7ed6-8a15-40ec-a8af-f5e712e0da68}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\modules\ogl\ogl.vcxproj">\r
+      <Project>{88f974f0-d09f-4788-8cf8-f563209e60c1}</Project>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\protocol\protocol.vcxproj">\r
+      <Project>{2040b361-1fb6-488e-84a5-38a580da90de}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <None Include="casparcg.config">\r
+      <SubType>Designer</SubType>\r
+    </None>\r
+    <None Include="CasparCG.ico" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="server.h" />\r
+    <ClInclude Include="resource.h" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ResourceCompile Include="shell.rc" />\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{8C26C94F-8092-4769-8D84-DEA479721C5B}</ProjectGuid>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <RootNamespace>shell</RootNamespace>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseDebugLibraries>true</UseDebugLibraries>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseDebugLibraries>false</UseDebugLibraries>\r
+    <WholeProgramOptimization>true</WholeProgramOptimization>\r
+    <CharacterSet>Unicode</CharacterSet>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(SolutionDir)tmp\$(Configuration)\</IntDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(SolutionDir)tmp\$(Configuration)\</IntDir>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.8\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.8\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.8\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\dependencies\BluefishSDK_V5_10_0_42\Inc\;..\dependencies\boost\;..\dependencies\ffmpeg 0.8\include\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\include;..\dependencies\SFML-1.6\include\;..\dependencies\tbb\include\;$(IncludePath)</IncludePath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program\Microsoft DirectX SDK (June 2010)\Lib\x86;..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.8\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;..\dependencies\zlib\lib;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program\Microsoft DirectX SDK (June 2010)\Lib\x86;..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.8\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;..\dependencies\zlib\lib;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">C:\Program\Microsoft DirectX SDK (June 2010)\Lib\x86;..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.8\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;..\dependencies\zlib\lib;$(LibraryPath)</LibraryPath>\r
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">C:\Program\Microsoft DirectX SDK (June 2010)\Lib\x86;..\dependencies\BluefishSDK_V5_10_0_42\Lib\;..\dependencies\boost\stage\lib\;..\dependencies\ffmpeg 0.8\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;..\dependencies\zlib\lib;$(LibraryPath)</LibraryPath>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(SolutionDir)bin\$(Configuration)\</OutDir>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(SolutionDir)bin\$(Configuration)\</OutDir>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(SolutionName)</TargetName>\r
+    <TargetName Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(SolutionName)</TargetName>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <LinkIncremental>true</LinkIncremental>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <LinkIncremental>false</LinkIncremental>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <LinkIncremental>true</LinkIncremental>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <LinkIncremental>true</LinkIncremental>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <SmallerTypeCheck>false</SmallerTypeCheck>\r
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_DEBUG;_DEBUG;_CRT_SECURE_NO_WARNINGS;COMPILE_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalDependencies>sfml-system-d.lib;sfml-audio-d.lib;sfml-window-d.lib;sfml-graphics-d.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>\r
+      <GenerateMapFile>false</GenerateMapFile>\r
+      <MapFileName>\r
+      </MapFileName>\r
+      <SubSystem>Console</SubSystem>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>\r
+      <MapExports>false</MapExports>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>copy "$(SolutionDir)dependencies\ffmpeg 0.8\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\FreeImage\Dist\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\glew-1.6.0\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\tbb\bin\ia32\vc10\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\zlib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\lib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\extlibs\bin\*.dll" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+    </PostBuildEvent>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;NDEBUG;_VC80_UPGRADE=0x0710;COMPILE_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>true</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>sfml-system.lib;sfml-audio.lib;sfml-window.lib;sfml-graphics.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>true</GenerateMapFile>\r
+      <MapExports>true</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>\r
+      <LargeAddressAware>true</LargeAddressAware>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>copy "$(SolutionDir)dependencies\ffmpeg 0.8\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\FreeImage\Dist\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\glew-1.6.0\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\tbb\bin\ia32\vc10\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\zlib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\lib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\extlibs\bin\*.dll" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+    </PostBuildEvent>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_THREADING_TOOLS=1;NDEBUG;_VC80_UPGRADE=0x0710;COMPILE_PROFILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>sfml-system.lib;sfml-audio.lib;sfml-window.lib;sfml-graphics.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>false</GenerateMapFile>\r
+      <MapExports>false</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>copy "$(SolutionDir)dependencies\ffmpeg 0.8\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\FreeImage\Dist\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\glew-1.6.0\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\tbb\bin\ia32\vc10\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\zlib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\lib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\extlibs\bin\*.dll" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+    </PostBuildEvent>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">\r
+    <PreBuildEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreBuildEvent>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>\r
+      <IntrinsicFunctions>true</IntrinsicFunctions>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>\r
+      <ExceptionHandling>Async</ExceptionHandling>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <PreprocessorDefinitions>TBB_USE_CAPTURED_EXCEPTION=0;TBB_USE_ASSERT=1;TBB_USE_PERFORMANCE_WARNINGS=1;NDEBUG;_VC80_UPGRADE=0x0710;COMPILE_DEVELOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <WholeProgramOptimization>false</WholeProgramOptimization>\r
+      <TreatWarningAsError>true</TreatWarningAsError>\r
+      <FloatingPointModel>Fast</FloatingPointModel>\r
+      <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
+    </ClCompile>\r
+    <PreLinkEvent>\r
+      <Command>\r
+      </Command>\r
+    </PreLinkEvent>\r
+    <Link>\r
+      <AdditionalDependencies>sfml-system.lib;sfml-audio.lib;sfml-window.lib;sfml-graphics.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <Version>\r
+      </Version>\r
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <GenerateMapFile>false</GenerateMapFile>\r
+      <MapExports>false</MapExports>\r
+      <SubSystem>Console</SubSystem>\r
+      <OptimizeReferences>\r
+      </OptimizeReferences>\r
+      <EnableCOMDATFolding>\r
+      </EnableCOMDATFolding>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <FixedBaseAddress>false</FixedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>\r
+    </Link>\r
+    <PostBuildEvent>\r
+      <Command>copy "$(SolutionDir)dependencies\ffmpeg 0.8\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\FreeImage\Dist\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\glew-1.6.0\bin\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\tbb\bin\ia32\vc10\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\zlib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\lib\*.dll" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies\SFML-1.6\extlibs\bin\*.dll" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+    </PostBuildEvent>\r
+  </ItemDefinitionGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/shell/shell.vcxproj.filters b/shell/shell.vcxproj.filters
new file mode 100644 (file)
index 0000000..9208de2
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <ClCompile Include="main.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="server.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <None Include="casparcg.config" />\r
+    <None Include="CasparCG.ico" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="server.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="resource.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{39e46848-dfec-441d-b0c0-f131380cdc6e}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ResourceCompile Include="shell.rc">\r
+      <Filter>source</Filter>\r
+    </ResourceCompile>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/version.tmpl b/version.tmpl
new file mode 100644 (file)
index 0000000..2431b7b
--- /dev/null
@@ -0,0 +1,5 @@
+#define CASPAR_GEN 2\r
+#define CASPAR_MAYOR 0\r
+#define CASPAR_MINOR 3\r
+#define CASPAR_REV $WCREV$\r
+#define CASPAR_TAG "STABLE"\r