<ClInclude Include="parameters\parameters.h" />\r
<ClInclude Include="monitor\monitor.h" />\r
<ClInclude Include="producer\channel\channel_producer.h" />\r
- <ClInclude Include="producer\media_info\file_based_media_info_repository.h" />\r
+ <ClInclude Include="producer\media_info\in_memory_media_info_repository.h" />\r
<ClInclude Include="producer\media_info\media_info.h" />\r
<ClInclude Include="producer\media_info\media_info_repository.h" />\r
<ClInclude Include="thumbnail_generator.h" />\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\media_info\file_based_media_info_repository.cpp">\r
+ <ClCompile Include="producer\media_info\in_memory_media_info_repository.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
<ClInclude Include="producer\media_info\media_info_repository.h">\r
<Filter>source\producer\media_info</Filter>\r
</ClInclude>\r
- <ClInclude Include="producer\media_info\file_based_media_info_repository.h">\r
+ <ClInclude Include="producer\media_info\in_memory_media_info_repository.h">\r
<Filter>source\producer\media_info</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ClCompile Include="parameters\parameters.cpp">\r
<Filter>source\parameters</Filter>\r
</ClCompile>\r
- <ClCompile Include="producer\media_info\file_based_media_info_repository.cpp">\r
+ <ClCompile Include="producer\media_info\in_memory_media_info_repository.cpp">\r
<Filter>source\producer\media_info</Filter>\r
</ClCompile>\r
</ItemGroup>\r
\r
#include "color/color_producer.h"\r
#include "separated/separated_producer.h"\r
-#include "media_info/media_info.h"\r
\r
#include <common/memory/safe_ptr.h>\r
#include <common/concurrency/executor.h>\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(media_info& additional_info) override {return (*producer_)->create_thumbnail_frame(additional_info);}\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
\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(media_info& additional_info) override {return (producer_)->create_thumbnail_frame(additional_info);}\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
\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(media_info&) {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
return producer;\r
}\r
\r
-safe_ptr<basic_frame> frame_producer::create_thumbnail_frame(media_info&)\r
+safe_ptr<basic_frame> frame_producer::create_thumbnail_frame()\r
{\r
return basic_frame::empty();\r
}\r
class basic_frame;\r
class parameters;\r
struct frame_factory;\r
-struct media_info;\r
\r
struct frame_producer : boost::noncopyable\r
{\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(media_info& additional_info);\r
+ virtual safe_ptr<basic_frame> create_thumbnail_frame();\r
\r
static const safe_ptr<frame_producer>& empty(); // nothrow\r
\r
+++ /dev/null
-/*
-* Copyright 2013 Sveriges Television AB http://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
-*/
-
-#include "../../StdAfx.h"
-
-#include "file_based_media_info_repository.h"
-
-#include <fstream>
-#include <vector>
-
-#include <boost/thread/mutex.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/foreach.hpp>
-#include <boost/filesystem.hpp>
-
-#include "media_info.h"
-#include "media_info_repository.h"
-
-namespace {
-
-static const std::wstring delimeter = L",";
-
-std::map<std::wstring, caspar::core::media_info> load(
- const std::wstring& csv_file)
-{
- std::map<std::wstring, caspar::core::media_info> result;
- std::wifstream stream(csv_file);
-
- if (!stream)
- return result;
-
- wchar_t line[1024];
-
- while (stream.getline(line, 1024))
- {
- std::vector<std::wstring> cells;
- boost::split(
- cells,
- line,
- boost::is_any_of(delimeter),
- boost::token_compress_on);
-
- if (cells.size() != 4)
- continue;
-
- auto filename = cells.at(0);
- caspar::core::media_info info;
-
- try
- {
- info.duration = boost::lexical_cast<int64_t>(cells.at(1));
- info.time_base = boost::rational<int64_t>(
- boost::lexical_cast<int64_t>(cells.at(2)),
- boost::lexical_cast<int64_t>(cells.at(3)));
- }
- catch (const boost::bad_lexical_cast&)
- {
- continue;
- }
-
- result.insert(std::make_pair(std::move(filename), std::move(info)));
- }
-
- return result;
-}
-
-void save(
- const std::map<std::wstring, caspar::core::media_info>& infos,
- const std::wstring& csv_file)
-{
- std::wstring tmp_file = csv_file + L".tmp";
- std::wofstream stream(tmp_file, std::ios::trunc);
-
- if (!stream)
- throw std::exception();
-
- BOOST_FOREACH(const auto& info, infos)
- {
- stream
- << info.first << delimeter
- << info.second.duration << delimeter
- << info.second.time_base.numerator() << delimeter
- << info.second.time_base.denominator() << L"\n";
- }
-
- stream << std::flush;
- stream.close();
-
- // The remove is unfortunately needed by the current version of boost.
- boost::filesystem::remove(csv_file);
- boost::filesystem::rename(tmp_file, csv_file);
-}
-
-}
-
-namespace caspar { namespace core {
-
-class file_based_media_info_repository : public media_info_repository
-{
- mutable boost::mutex mutex_;
- std::wstring csv_file_;
- std::map<std::wstring, media_info> info_by_media_file_;
-public:
- file_based_media_info_repository(std::wstring csv_file)
- : csv_file_(std::move(csv_file))
- , info_by_media_file_(load(csv_file_))
- {
- }
-
- virtual void store(std::wstring media_file, media_info info) override
- {
- boost::mutex::scoped_lock lock(mutex_);
-
- info_by_media_file_[std::move(media_file)] = info;
-
- save(info_by_media_file_, csv_file_);
- }
-
- virtual bool try_load(
- const std::wstring& media_file, media_info& info) const override
- {
- boost::mutex::scoped_lock lock(mutex_);
-
- auto iter = info_by_media_file_.find(media_file);
-
- if (iter == info_by_media_file_.end())
- return false;
-
- info = iter->second;
-
- return true;
- }
-
- virtual void remove(const std::wstring& media_file) override
- {
- boost::mutex::scoped_lock lock(mutex_);
-
- info_by_media_file_.erase(media_file);
-
- save(info_by_media_file_, csv_file_);
- }
-};
-
-safe_ptr<struct media_info_repository> create_file_based_media_info_repository(
- std::wstring csv_file)
-{
- return make_safe<file_based_media_info_repository>(std::move(csv_file));
-}
-
-}}
--- /dev/null
+/*
+* Copyright 2013 Sveriges Television AB http://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
+*/
+
+#include "../../StdAfx.h"
+
+#include "in_memory_media_info_repository.h"
+
+#include <map>
+#include <vector>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/foreach.hpp>
+
+#include "media_info.h"
+#include "media_info_repository.h"
+
+namespace caspar { namespace core {
+
+class in_memory_media_info_repository : public media_info_repository
+{
+ boost::mutex mutex_;
+ std::map<std::wstring, media_info> info_by_file_;
+ std::vector<media_info_extractor> extractors_;
+public:
+ virtual void register_extractor(media_info_extractor extractor) override
+ {
+ boost::mutex::scoped_lock lock(mutex_);
+
+ extractors_.push_back(extractor);
+ }
+
+ virtual media_info get(const std::wstring& file) override
+ {
+ boost::mutex::scoped_lock lock(mutex_);
+
+ auto iter = info_by_file_.find(file);
+
+ if (iter == info_by_file_.end())
+ {
+ media_info info;
+
+ BOOST_FOREACH(auto& extractor, extractors_)
+ {
+ if (extractor(file, info))
+ {
+ break;
+ }
+ }
+
+ info_by_file_.insert(std::make_pair(file, info));
+
+ return info;
+ }
+
+ return iter->second;
+ }
+
+ virtual void remove(const std::wstring& file) override
+ {
+ boost::mutex::scoped_lock lock(mutex_);
+
+ info_by_file_.erase(file);
+ }
+};
+
+safe_ptr<struct media_info_repository> create_in_memory_media_info_repository()
+{
+ return make_safe<in_memory_media_info_repository>();
+}
+
+}}
namespace caspar { namespace core {
-safe_ptr<struct media_info_repository> create_file_based_media_info_repository(
- std::wstring csv_file);
+safe_ptr<struct media_info_repository> create_in_memory_media_info_repository();
}}
#pragma once
#include <string>
+#include <functional>
namespace caspar { namespace core {
struct media_info;
+typedef std::function<bool (const std::wstring& f, media_info& info)> media_info_extractor;
struct media_info_repository
{
virtual ~media_info_repository() { }
- virtual void store(std::wstring media_file, media_info info) = 0;
- virtual bool try_load(
- const std::wstring& media_file, media_info& info) const = 0;
- virtual void remove(const std::wstring& media_file) = 0;
+ virtual void register_extractor(media_info_extractor extractor) = 0;
+ virtual media_info get(const std::wstring& file) = 0;
+ virtual void remove(const std::wstring& file) = 0;
};
}}
#include "separated_producer.h"\r
\r
#include <core/producer/frame/basic_frame.h>\r
-#include <core/producer/media_info/media_info.h>\r
\r
#include <tbb/parallel_invoke.h>\r
\r
return disable_audio(last_frame_);\r
}\r
\r
- virtual safe_ptr<basic_frame> create_thumbnail_frame(media_info& additional_info) override\r
+ virtual safe_ptr<basic_frame> create_thumbnail_frame() override\r
{\r
- auto fill_frame = fill_producer_->create_thumbnail_frame(additional_info);\r
- media_info dummy;\r
- auto key_frame = key_producer_->create_thumbnail_frame(dummy);\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
== relative_without_extensions.end();\r
\r
if (no_corresponding_media_file)\r
- remove_thumbnail(relative_without_extension);\r
+ remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
}\r
}\r
\r
\r
break;\r
case REMOVED:\r
- remove_thumbnail(get_relative_without_extension(file, media_path_));\r
+ auto relative_without_extension = get_relative_without_extension(file, media_path_);\r
+ boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
+ media_info_repo_->remove(file.file_string());\r
\r
break;\r
}\r
}\r
\r
- void remove_thumbnail(const std::wstring& relative_without_extension)\r
- {\r
- boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
- media_info_repo_->remove(relative_without_extension);\r
- }\r
-\r
bool needs_to_be_generated(const boost::filesystem::wpath& file)\r
{\r
using namespace boost::filesystem;\r
\r
std::map<int, safe_ptr<basic_frame>> frames;\r
auto raw_frame = basic_frame::empty();\r
- media_info additional_info;\r
\r
try\r
{\r
- raw_frame = producer->create_thumbnail_frame(additional_info);\r
- media_info_repo_->store(media_file, additional_info);\r
+ raw_frame = producer->create_thumbnail_frame();\r
+ media_info_repo_->remove(file.file_string());\r
+ media_info_repo_->get(file.file_string());\r
}\r
catch (const boost::thread_interrupted&)\r
{\r
\r
#include "consumer/ffmpeg_consumer.h"\r
#include "producer/ffmpeg_producer.h"\r
+#include "producer/util/util.h"\r
\r
#include <common/log/log.h>\r
#include <common/exception/win32_exception.h>\r
#include <core/parameters/parameters.h>\r
#include <core/consumer/frame_consumer.h>\r
#include <core/producer/frame_producer.h>\r
+#include <core/producer/media_info/media_info.h>\r
+#include <core/producer/media_info/media_info_repository.h>\r
\r
#include <tbb/recursive_mutex.h>\r
\r
//}\r
//#pragma warning (pop)\r
\r
-void init()\r
+void init(const safe_ptr<core::media_info_repository>& media_info_repo)\r
{\r
av_lockmgr_register(ffmpeg_lock_callback);\r
av_log_set_callback(log_for_thread);\r
core::register_consumer_factory([](const core::parameters& params){return ffmpeg::create_consumer(params);});\r
core::register_producer_factory(create_producer);\r
core::register_thumbnail_producer_factory(create_thumbnail_producer);\r
+\r
+ media_info_repo->register_extractor(\r
+ [](const std::wstring& file, core::media_info& info) -> bool\r
+ {\r
+ auto disable_logging = temporary_disable_logging_for_thread(true);\r
+\r
+ return is_valid_file(file) && try_get_duration(file, info.duration, info.time_base);\r
+ });\r
}\r
\r
void uninit()\r
#include <string>\r
#include <memory>\r
\r
-namespace caspar { namespace ffmpeg {\r
+namespace caspar { \r
+namespace core {\r
\r
-void init();\r
+struct media_info_repository;\r
+\r
+}\r
+\r
+namespace ffmpeg {\r
+\r
+void init(const safe_ptr<core::media_info_repository>& media_info_repo);\r
void uninit();\r
void disable_logging_for_thread();\r
std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable);\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
-#include <core/producer/media_info/media_info.h>\r
\r
#include <boost/algorithm/string.hpp>\r
#include <boost/assign.hpp>\r
return core::basic_frame::empty();\r
}\r
\r
- virtual safe_ptr<core::basic_frame> create_thumbnail_frame(core::media_info& additional_info) override\r
+ virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
{\r
auto disable_logging = temporary_disable_logging_for_thread(thumbnail_mode_);\r
\r
auto total_frames = nb_frames();\r
auto grid = env::properties().get(L"configuration.thumbnails.video-grid", 2);\r
\r
- try_get_duration(*input_.context(), additional_info.duration, additional_info.time_base);\r
-\r
if (grid < 1)\r
{\r
CASPAR_LOG(error) << L"configuration/thumbnails/video-grid cannot be less than 1";\r
return is_valid_file(filename, invalid_exts);\r
}\r
\r
-bool try_get_duration(AVFormatContext& context, std::int64_t& duration, boost::rational<std::int64_t>& time_base)\r
-{ \r
- const auto fps = read_fps(context, 1.0);\r
- const auto rational_fps = boost::rational<std::int64_t>(static_cast<int>(fps * AV_TIME_BASE), AV_TIME_BASE);\r
- \r
- duration = boost::rational_cast<std::int64_t>(context.duration * rational_fps / AV_TIME_BASE);\r
-\r
- if (rational_fps == 0)\r
- return false;\r
-\r
- time_base = 1/rational_fps;\r
-\r
- return true;\r
-}\r
-\r
bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base)\r
-{ \r
+{\r
AVFormatContext* weak_context = nullptr;\r
if(avformat_open_input(&weak_context, narrow(filename).c_str(), nullptr, nullptr) < 0)\r
return false;\r
\r
std::shared_ptr<AVFormatContext> context(weak_context, av_close_input_file);\r
-\r
+ \r
context->probesize = context->probesize / 10;\r
context->max_analyze_duration = context->probesize / 10;\r
\r
if(avformat_find_stream_info(context.get(), nullptr) < 0)\r
return false;\r
+\r
+ const auto fps = read_fps(*context, 1.0);\r
+ \r
+ const auto rational_fps = boost::rational<std::int64_t>(static_cast<int>(fps * AV_TIME_BASE), AV_TIME_BASE);\r
\r
- return try_get_duration(*context, duration, time_base);\r
+ duration = boost::rational_cast<std::int64_t>(context->duration * rational_fps / AV_TIME_BASE);\r
+\r
+ if (rational_fps == 0)\r
+ return false;\r
+\r
+ time_base = 1/rational_fps;\r
+\r
+ return true;\r
}\r
\r
std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts)\r
std::wstring probe_stem(const std::wstring stem);\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
-bool try_get_duration(AVFormatContext& context, std::int64_t& duration, boost::rational<std::int64_t>& time_base);\r
bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base);\r
\r
core::channel_layout get_audio_channel_layout(const AVCodecContext& context, const std::wstring& custom_channel_order);\r
#include <core/monitor/monitor.h>\r
#include <core/producer/frame/basic_frame.h>\r
#include <core/producer/frame/frame_factory.h>\r
-#include <core/producer/media_info/media_info.h>\r
#include <core/mixer/write_frame.h>\r
\r
#include <common/env.h>\r
return frame_;\r
}\r
\r
- virtual safe_ptr<core::basic_frame> create_thumbnail_frame(core::media_info& additional_info) override\r
+ virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
{\r
return frame_;\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
- core::media_info media_info;\r
- media_info_repo->try_load(boost::replace_all_copy(str, "\\", "/"), media_info);\r
+ auto media_info = media_info_repo->get(path.file_string());\r
\r
return std::wstring() \r
+ L"\"" + str +\r
#include <core/consumer/output.h>\r
#include <core/consumer/synchronizing/synchronizing_consumer.h>\r
#include <core/thumbnail_generator.h>\r
+#include <core/producer/media_info/media_info.h>\r
#include <core/producer/media_info/media_info_repository.h>\r
-#include <core/producer/media_info/file_based_media_info_repository.h>\r
+#include <core/producer/media_info/in_memory_media_info_repository.h>\r
\r
#include <modules/bluefish/bluefish.h>\r
#include <modules/decklink/decklink.h>\r
\r
#include <boost/algorithm/string.hpp>\r
#include <boost/lexical_cast.hpp>\r
+#include <boost/filesystem.hpp>\r
#include <boost/foreach.hpp>\r
#include <boost/property_tree/ptree.hpp>\r
#include <boost/property_tree/xml_parser.hpp>\r
#include <boost/asio.hpp>\r
\r
+#include <tbb/atomic.h>\r
+\r
namespace caspar {\r
\r
using namespace core;\r
std::vector<std::shared_ptr<void>> predefined_osc_subscriptions_;\r
std::vector<safe_ptr<video_channel>> channels_;\r
safe_ptr<media_info_repository> media_info_repo_;\r
+ boost::thread initial_media_info_thread_;\r
+ tbb::atomic<bool> running_;\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
, osc_client_(io_service_)\r
- , media_info_repo_(create_file_based_media_info_repository(\r
- env::thumbnails_folder() + L"media_info.csv"))\r
+ , media_info_repo_(create_in_memory_media_info_repository())\r
{\r
+ running_ = true;\r
setup_audio(env::properties());\r
\r
- ffmpeg::init();\r
+ ffmpeg::init(media_info_repo_);\r
CASPAR_LOG(info) << L"Initialized ffmpeg module.";\r
\r
bluefish::init(); \r
\r
setup_osc(env::properties());\r
CASPAR_LOG(info) << L"Initialized osc.";\r
+\r
+ start_initial_media_info_scan();\r
+ CASPAR_LOG(info) << L"Started initial media information retrieval.";\r
}\r
\r
~implementation()\r
{\r
+ running_ = false;\r
+ initial_media_info_thread_.join();\r
thumbnail_generator_.reset();\r
primary_amcp_server_.reset();\r
async_servers_.clear();\r
\r
BOOST_THROW_EXCEPTION(caspar_exception() << arg_name_info("name") << arg_value_info(narrow(name)) << msg_info("Invalid protocol"));\r
}\r
+\r
+ void start_initial_media_info_scan()\r
+ {\r
+ initial_media_info_thread_ = boost::thread([this]\r
+ {\r
+ for (boost::filesystem::wrecursive_directory_iterator iter(env::media_folder()), end; iter != end; ++iter)\r
+ {\r
+ if (running_)\r
+ media_info_repo_->get(iter->path().file_string());\r
+ else\r
+ {\r
+ CASPAR_LOG(info) << L"Initial media information retrieval aborted.";\r
+ return;\r
+ }\r
+ }\r
+\r
+ CASPAR_LOG(info) << L"Initial media information retrieval finished.";\r
+ });\r
+ }\r
};\r
\r
server::server(boost::promise<bool>& shutdown_server_now) : impl_(new implementation(shutdown_server_now)){}\r