2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>
\r
4 * This file is part of CasparCG.
\r
6 * CasparCG is free software: you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation, either version 3 of the License, or
\r
9 * (at your option) any later version.
\r
11 * CasparCG is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
\r
20 #include "../../stdafx.h"
\r
22 #include "playlist_producer.h"
\r
24 #include <core/producer/frame_producer.h>
\r
25 #include <core/producer/frame/basic_frame.h>
\r
27 #include <boost/regex.hpp>
\r
31 namespace caspar { namespace core {
\r
33 struct playlist_producer : public frame_producer
\r
35 safe_ptr<frame_factory> factory_;
\r
36 safe_ptr<basic_frame> last_frame_;
\r
37 safe_ptr<frame_producer> current_;
\r
40 std::deque<safe_ptr<frame_producer>> producers_;
\r
42 playlist_producer(const safe_ptr<frame_factory>& factory, bool loop)
\r
44 , last_frame_(basic_frame::empty())
\r
45 , current_(frame_producer::empty())
\r
52 virtual safe_ptr<basic_frame> receive(int hints) override
\r
54 if(current_ == frame_producer::empty() && !producers_.empty())
\r
56 current_ = producers_.front();
\r
57 producers_.pop_front();
\r
59 producers_.push_back(current_);
\r
62 auto frame = current_->receive(hints);
\r
63 if(frame == basic_frame::eof())
\r
65 current_ = frame_producer::empty();
\r
66 return receive(hints);
\r
69 return last_frame_ = frame;
\r
72 virtual safe_ptr<core::basic_frame> last_frame() const override
\r
74 return disable_audio(last_frame_);
\r
77 virtual std::wstring print() const override
\r
79 return L"playlist[]";
\r
82 virtual int64_t nb_frames() const override
\r
84 return std::numeric_limits<int>::max();
\r
87 virtual boost::unique_future<std::wstring> call(const std::wstring& param) override
\r
89 boost::promise<std::wstring> promise;
\r
90 promise.set_value(do_call(param));
\r
91 return promise.get_future();
\r
94 // playlist_producer
\r
96 std::wstring do_call(const std::wstring& param)
\r
98 static const boost::wregex push_front_exp (L"PUSH_FRONT (?<PARAM>.+)");
\r
99 static const boost::wregex push_back_exp (L"(PUSH_BACK|PUSH) (?<PARAM>.+)");
\r
100 static const boost::wregex pop_front_exp (L"POP_FRONT");
\r
101 static const boost::wregex pop_back_exp (L"(POP_BACK|POP)");
\r
102 static const boost::wregex insert_exp (L"INSERT (?<POS>\\d+) (?<PARAM>.+)");
\r
103 static const boost::wregex remove_exp (L"REMOVE (?<POS>\\d+) (?<PARAM>.+)");
\r
104 static const boost::wregex list_exp (L"LIST");
\r
105 static const boost::wregex loop_exp (L"LOOP\\s*(?<VALUE>\\d?)");
\r
107 boost::wsmatch what;
\r
109 if(boost::regex_match(param, what, push_front_exp))
\r
110 return push_front(what["PARAM"].str());
\r
111 else if(boost::regex_match(param, what, push_back_exp))
\r
112 return push_back(what["PARAM"].str());
\r
113 if(boost::regex_match(param, what, pop_front_exp))
\r
114 return pop_front();
\r
115 else if(boost::regex_match(param, what, pop_back_exp))
\r
116 return pop_back();
\r
117 else if(boost::regex_match(param, what, insert_exp))
\r
118 return insert(boost::lexical_cast<size_t>(what["POS"].str()), what["PARAM"].str());
\r
119 else if(boost::regex_match(param, what, remove_exp))
\r
120 return erase(boost::lexical_cast<size_t>(what["POS"].str()));
\r
121 else if(boost::regex_match(param, what, list_exp))
\r
123 else if(boost::regex_match(param, what, loop_exp))
\r
125 if(!what["VALUE"].str().empty())
\r
126 loop_ = boost::lexical_cast<bool>(what["VALUE"].str());
\r
127 return boost::lexical_cast<std::wstring>(loop_);
\r
130 BOOST_THROW_EXCEPTION(invalid_argument());
\r
133 std::wstring push_front(const std::wstring& str)
\r
135 producers_.push_front(create_producer(factory_, str));
\r
139 std::wstring push_back(const std::wstring& str)
\r
141 producers_.push_back(create_producer(factory_, str));
\r
145 std::wstring pop_front()
\r
147 producers_.pop_front();
\r
151 std::wstring pop_back()
\r
153 producers_.pop_back();
\r
157 std::wstring insert(size_t pos, const std::wstring& str)
\r
159 if(pos >= producers_.size())
\r
160 BOOST_THROW_EXCEPTION(out_of_range());
\r
161 producers_.insert(std::begin(producers_) + pos, create_producer(factory_, str));
\r
165 std::wstring erase(size_t pos)
\r
167 if(pos >= producers_.size())
\r
168 BOOST_THROW_EXCEPTION(out_of_range());
\r
169 producers_.erase(std::begin(producers_) + pos);
\r
173 std::wstring list() const
\r
175 std::wstring result = L"<playlist>";
\r
176 BOOST_FOREACH(auto& producer, producers_)
\r
177 result += L"\t<producer>" + producer->print() + L"</producer>\n";
\r
178 return result + L"</playlist>";
\r
182 safe_ptr<frame_producer> create_playlist_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)
\r
184 if(boost::range::find(params, L"[PLAYLIST]") == params.end())
\r
185 return core::frame_producer::empty();
\r
187 bool loop = boost::range::find(params, L"LOOP") != params.end();
\r
189 return make_safe<playlist_producer>(frame_factory, loop);
\r