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];
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
{
}
}
- if (execute_rest_)
- {
- execute_rest(high_priority);
- execute_rest(normal_priority);
- }
+ execute_rest(high_priority);
+ execute_rest(normal_priority);
}
};
#include <set>\r
#include <iostream>\r
\r
-#include <boost/thread.hpp>\r
+#include <boost/asio.hpp>\r
#include <boost/foreach.hpp>\r
#include <boost/range/adaptor/map.hpp>\r
#include <boost/range/algorithm/copy.hpp>\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
class polling_filesystem_monitor : public filesystem_monitor\r
{\r
directory_monitor root_monitor_;\r
- boost::thread scanning_thread_;\r
+ executor executor_;\r
+ boost::asio::io_service& scheduler_;\r
+ boost::asio::deadline_timer timer_;\r
tbb::atomic<bool> running_;\r
int scan_interval_millis_;\r
boost::promise<void> initial_scan_completion_;\r
filesystem_event events_of_interest_mask,\r
bool report_already_existing,\r
int scan_interval_millis,\r
+ boost::asio::io_service& scheduler,\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
+ : root_monitor_(\r
+ report_already_existing,\r
+ folder_to_watch,\r
+ events_of_interest_mask,\r
+ handler,\r
+ initial_files_handler)\r
+ , executor_(L"polling_filesystem_monitor")\r
+ , scheduler_(scheduler)\r
+ , timer_(scheduler)\r
, scan_interval_millis_(scan_interval_millis)\r
{\r
running_ = true;\r
reemmit_all_ = false;\r
- scanning_thread_ = boost::thread([this] { scanner(); });\r
+ executor_.begin_invoke([this]\r
+ {\r
+ scan();\r
+ initial_scan_completion_.set_value();\r
+ schedule_next();\r
+ });\r
}\r
\r
virtual ~polling_filesystem_monitor()\r
{\r
running_ = false;\r
- scanning_thread_.interrupt();\r
- scanning_thread_.join();\r
+ boost::system::error_code e;\r
+ timer_.cancel(e);\r
}\r
\r
virtual boost::unique_future<void> initial_files_processed()\r
to_reemmit_.push(file);\r
}\r
private:\r
- void scanner()\r
+ void schedule_next()\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
+ if (!running_)\r
+ return;\r
\r
- if (running)\r
- while (scan(true));\r
+ timer_.expires_from_now(\r
+ boost::posix_time::milliseconds(scan_interval_millis_));\r
+ timer_.async_wait([this](const boost::system::error_code& e)\r
+ {\r
+ scan();\r
+ schedule_next();\r
+ });\r
}\r
\r
- bool scan(bool sleep)\r
+ void scan()\r
{\r
+ if (!running_)\r
+ return;\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
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
+ boost::asio::io_service& scheduler_;\r
int scan_interval_millis;\r
\r
- implementation(int scan_interval_millis)\r
- : scan_interval_millis(scan_interval_millis)\r
+ implementation(\r
+ boost::asio::io_service& scheduler, int scan_interval_millis)\r
+ : scheduler_(scheduler), 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
+polling_filesystem_monitor_factory::polling_filesystem_monitor_factory(\r
+ boost::asio::io_service& scheduler,\r
+ int scan_interval_millis)\r
+ : impl_(new implementation(scheduler, scan_interval_millis))\r
{\r
}\r
\r
events_of_interest_mask,\r
report_already_existing,\r
impl_->scan_interval_millis,\r
+ impl_->scheduler_,\r
handler,\r
initial_files_handler);\r
}\r
\r
#include "filesystem_monitor.h"\r
\r
+namespace boost { namespace asio {\r
+ class io_service;\r
+}}\r
+\r
namespace caspar {\r
\r
/**\r
/**\r
* Constructor.\r
*\r
+ * @param scheduler The io_service that will be used for\r
+ * scheduling periodic scans.\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
+ * scheduled scan. Lower values lowers the\r
+ * reaction time but causes more I/O.\r
*/\r
- polling_filesystem_monitor_factory(int scan_interval_millis = 5000);\r
+ polling_filesystem_monitor_factory(\r
+ boost::asio::io_service& scheduler,\r
+ 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
implementation(const safe_ptr<diagnostics::graph>& graph)\r
: graph_(graph)\r
, format_desc_(video_format_desc::get(video_format::invalid))\r
- , channel_layout_(default_channel_layout_repository().get_by_name(L"STEREO"))\r
+ , channel_layout_(channel_layout::stereo())\r
, master_volume_(1.0f)\r
, previous_master_volume_(master_volume_)\r
{\r
return channel_names.empty();
}
+const channel_layout& channel_layout::stereo()
+{
+ static channel_layout layout = create_layout_from_string(
+ L"stereo", L"2.0", 2, L"L R");
+
+ return layout;
+}
+
mix_config::mix_config()
: strategy(add)
{
{
repository.register_layout(create_layout_from_string(
L"mono", L"1.0", 1, L"C"));
- repository.register_layout(create_layout_from_string(
- L"stereo", L"2.0", 2, L"L R"));
+ repository.register_layout(channel_layout::stereo());
repository.register_layout(create_layout_from_string(
L"dts", L"5.1", 6, L"C L R Ls Rs LFE"));
repository.register_layout(create_layout_from_string(
int channel_index(const std::wstring& channel_name) const;\r
bool has_channel(const std::wstring& channel_name) const;\r
bool no_channel_names() const;\r
+\r
+ static const channel_layout& stereo();\r
};\r
\r
/**\r
virtual safe_ptr<write_frame> create_frame(\r
const void* video_stream_tag,\r
const pixel_format_desc& desc,\r
- const channel_layout& audio_channel_layout = default_channel_layout_repository().get_by_name(L"STEREO")) = 0; \r
+ const channel_layout& audio_channel_layout = channel_layout::stereo()) = 0; \r
\r
virtual video_format_desc get_video_format_desc() const = 0; // nothrow\r
};\r
output_,\r
format_desc_,\r
ogl,\r
- default_channel_layout_repository().get_by_name(L"STEREO")))\r
+ channel_layout::stereo()))\r
, thumbnail_creator_(thumbnail_creator)\r
, monitor_(monitor_factory.create(\r
media_path,\r
#include "../util/blue_velvet.h"\r
#include "../util/memory.h"\r
\r
-#include <core/parameters/parameters.h>
+#include <core/parameters/parameters.h>\r
#include <core/video_format.h>\r
#include <core/mixer/read_frame.h>\r
\r
}\r
}; \r
\r
-safe_ptr<core::frame_consumer> create_consumer(const core::parameters& params)
+safe_ptr<core::frame_consumer> create_consumer(const core::parameters& params)\r
{\r
if(params.size() < 1 || params[0] != L"BLUEFISH")\r
return core::frame_consumer::empty();\r
#include <common/memory/memclr.h>\r
#include <common/memory/memshfl.h>\r
\r
-#include <core/parameters/parameters.h>
+#include <core/parameters/parameters.h>\r
#include <core/consumer/frame_consumer.h>\r
#include <core/mixer/audio/audio_util.h>\r
\r
}\r
}; \r
\r
-safe_ptr<core::frame_consumer> create_consumer(const core::parameters& params)
+safe_ptr<core::frame_consumer> create_consumer(const core::parameters& params) \r
{\r
if(params.size() < 1 || params[0] != L"DECKLINK")\r
return core::frame_consumer::empty();\r
\r
~ffmpeg_consumer()\r
{ \r
- encode_executor_.stop_execute_rest();\r
+ encode_executor_.stop();\r
encode_executor_.join();\r
\r
// Flush\r
\r
ffmpeg_params vid_params;\r
\r
- return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, FFMPEG_FILE, filter_str, loop, start, length, true, L"", vid_params));\r
+ return make_safe<ffmpeg_producer>(frame_factory, filename, FFMPEG_FILE, filter_str, loop, start, length, true, L"", vid_params);\r
}\r
\r
}}
\ No newline at end of file
{ \r
ffmpeg::uninit();\r
\r
+ thumbnail_generator_.reset();\r
primary_amcp_server_.reset();\r
async_servers_.clear();\r
channels_.clear();\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
+ polling_filesystem_monitor_factory monitor_factory(\r
+ io_service_manager_.service(),\r
+ scan_interval_millis);\r
thumbnail_generator_.reset(new thumbnail_generator(\r
monitor_factory, \r
env::media_folder(),\r