{\r
producer->set_parent_printer(std::bind(&layer::print, &layers_.at(index)));\r
producer->initialize(factory_);\r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).load(producer, play_on_load);\r
- });\r
+ executor_.invoke([&]{layers_.at(index).load(producer, play_on_load);});\r
}\r
\r
void preview(size_t index, const safe_ptr<frame_producer>& producer)\r
{\r
producer->initialize(factory_);\r
- executor_.invoke([&]\r
- { \r
- layers_.at(index).preview(producer);\r
- });\r
+ executor_.invoke([&]{layers_.at(index).preview(producer);});\r
}\r
\r
void pause(size_t index)\r
{ \r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).pause();\r
- });\r
+ executor_.invoke([&]{layers_.at(index).pause();});\r
}\r
\r
void play(size_t index)\r
{ \r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).play();\r
- });\r
+ executor_.invoke([&]{layers_.at(index).play();});\r
}\r
\r
void stop(size_t index)\r
{ \r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).stop();\r
- });\r
+ executor_.invoke([&]{layers_.at(index).stop();});\r
}\r
\r
void clear(size_t index)\r
{\r
- executor_.invoke([&]\r
- {\r
- layers_.at(index) = std::move(layer(index, parent_printer_));\r
- });\r
+ executor_.invoke([&]{layers_.at(index).clear();});\r
}\r
\r
void clear()\r
{\r
executor_.invoke([&]\r
{\r
- for(size_t n = 0; n < layers_.size(); ++n)\r
- layers_[n] = layer(n, parent_printer_);\r
+ BOOST_FOREACH(auto& layer, layers_)\r
+ layer.clear();\r
});\r
} \r
\r
void swap_layer(size_t index, size_t other_index)\r
{\r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).swap(layers_[other_index]);\r
- });\r
+ layers_.at(index).swap(layers_[other_index]);\r
}\r
\r
void swap_layer(size_t index, size_t other_index, frame_producer_device& other)\r
{\r
- executor_.invoke([&]\r
- {\r
- layers_.at(index).swap(other.impl_->layers_.at(other_index));\r
- });\r
+ layers_.at(index).swap(other.impl_->layers_.at(other_index));\r
}\r
\r
void swap_output(frame_producer_device& other)\r
#include <mixer/audio/audio_mixer.h>\r
#include <mixer/audio/audio_transform.h>\r
\r
+#include <tbb/recursive_mutex.h>\r
+\r
namespace caspar { namespace core {\r
\r
class frame_producer_remover\r
\r
struct layer::implementation : boost::noncopyable\r
{ \r
+ tbb::recursive_mutex mutex_;\r
printer parent_printer_;\r
+ tbb::atomic<int> index_;\r
+\r
safe_ptr<frame_producer> foreground_;\r
safe_ptr<frame_producer> background_;\r
safe_ptr<draw_frame> last_frame_;\r
bool is_paused_;\r
- tbb::atomic<int> index_;\r
public:\r
implementation(int index, const printer& parent_printer) \r
: parent_printer_(parent_printer)\r
}\r
\r
void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
- { \r
+ { \r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+\r
background_ = frame_producer;\r
is_paused_ = false;\r
if(play_on_load)\r
\r
void preview(const safe_ptr<frame_producer>& frame_producer)\r
{\r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+\r
load(frame_producer, true);\r
receive();\r
pause();\r
}\r
\r
void play()\r
- { \r
+ { \r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+ \r
if(!is_paused_) \r
{\r
background_->set_leading_producer(foreground_);\r
\r
void pause()\r
{\r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+\r
is_paused_ = true;\r
}\r
\r
void stop()\r
{\r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+\r
pause();\r
last_frame_ = draw_frame::empty();\r
foreground_ = frame_producer::empty();\r
\r
void clear()\r
{\r
- stop();\r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+ \r
+ foreground_ = frame_producer::empty();\r
background_ = frame_producer::empty();\r
+ last_frame_ = draw_frame::empty();\r
+ is_paused_ = false;\r
}\r
\r
safe_ptr<draw_frame> receive()\r
{ \r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+\r
if(is_paused_)\r
{\r
last_frame_->get_audio_transform().set_gain(0.0);\r
return last_frame_;\r
}\r
\r
+ void swap(implementation& other)\r
+ {\r
+ tbb::recursive_mutex::scoped_lock lock(mutex_);\r
+ std::swap(foreground_, other.foreground_);\r
+ std::swap(background_, other.background_);\r
+ std::swap(last_frame_, other.last_frame_);\r
+ std::swap(is_paused_, other.is_paused_);\r
+ }\r
+ \r
std::wstring print() const\r
{\r
return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]";\r
}\r
};\r
\r
-layer::layer(int index, const printer& parent_printer) \r
-{\r
- impl_ = new implementation(index, parent_printer);\r
-}\r
-layer::layer(layer&& other) \r
-{\r
- impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
-}\r
-layer::~layer()\r
-{\r
- delete impl_.fetch_and_store(nullptr);\r
-}\r
+layer::layer(int index, const printer& parent_printer) : impl_(new implementation(index, parent_printer)){}\r
+layer::layer(layer&& other) : impl_(std::move(other.impl_)){}\r
layer& layer::operator=(layer&& other)\r
{\r
- impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
+ impl_ = std::move(other.impl_);\r
return *this;\r
}\r
void layer::swap(layer& other)\r
{\r
- impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
- impl_->index_ = other.impl_->index_.compare_and_swap(impl_->index_, other.impl_->index_);\r
+ impl_->swap(*other.impl_);\r
}\r
void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);} \r
void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);} \r
\r
#include <tbb/atomic.h>\r
\r
+#include <memory>\r
+\r
namespace caspar { namespace core {\r
\r
class frame_producer;\r
public:\r
layer(int index, const printer& parent_printer = nullptr); // nothrow\r
layer(layer&& other); // nothrow\r
- ~layer(); // nothrow\r
layer& operator=(layer&& other); // nothrow\r
\r
- //NOTE: swap is thread-safe on "other", NOT on "this".\r
void swap(layer& other); // nothrow \r
\r
void load(const safe_ptr<frame_producer>& producer, bool play_on_load = false); // nothrow\r
std::wstring print() const;\r
private:\r
struct implementation;\r
- tbb::atomic<implementation*> impl_;\r
+ std::shared_ptr<implementation> impl_;\r
};\r
\r
}}
\ No newline at end of file