55 class LoadHelper :
public GenericConverter {
57 explicit LoadHelper(
double value) : value_(value) {}
59 bool TryConvert(Handle<JsValue> )
override {
60 LOG(FATAL) <<
"Not reached";
63 ReturnVal<JsValue>
ToJsValue()
const override {
88 CHECK(engine) <<
"Must pass a JsManager instance";
92 CallMethod<void>(
"destroy").wait();
109 LOG(ERROR) <<
"Cannot get 'shaka.Player' object; is " 110 "shaka-player.compiled.js corrupted?";
111 return Error(
"The constructor 'shaka.Player' is not found.");
113 LocalVar<JsFunction> player_ctor_func =
114 UnsafeJsCast<JsFunction>(player_ctor);
116 LocalVar<JsValue> result_or_except;
117 std::vector<LocalVar<JsValue>> args;
121 args.emplace_back(video_->JsThis());
124 &result_or_except)) {
125 return ConvertError(result_or_except);
128 Init(UnsafeJsCast<JsObject>(result_or_except));
129 return AttachListeners(client);
141 auto future = CallMethod<void>(
"attach", new_elem);
142 return SetVideoWhenResolved(future, new_elem);
146 auto future = CallMethod<void>(
"detach");
147 return SetVideoWhenResolved(future,
nullptr);
150 template <
typename T>
152 const std::string& name_path) {
153 auto callback = std::bind(&Impl::GetConfigValueRaw<T>,
this, name_path);
155 std::move(callback));
159 std::unique_lock<Mutex> lock(filters_mutex_);
160 filters_.emplace_back(filters);
164 std::unique_lock<Mutex> lock(filters_mutex_);
182 auto results = future.get();
183 if (!holds_alternative<Error>(results)) {
192 return std::async(std::launch::deferred, std::move(then));
195 template <
typename T>
196 using filter_member_t =
199 template <
typename T>
201 const std::string& name_path) {
203 LocalVar<JsValue> configuration;
204 auto error = CallMemberFunction(object_,
"getConfiguration", 0,
nullptr,
206 if (holds_alternative<Error>(error))
207 return get<Error>(error);
214 GetDescendant(UnsafeJsCast<JsObject>(configuration), components);
220 #define ATTACH(name, call) \ 222 const auto ret = AttachEventListener( \ 223 name, std::bind(&Client::OnError, client, std::placeholders::_1), \ 225 if (holds_alternative<Error>(ret)) \ 226 return get<Error>(ret); \ 229 const auto on_error = [=](Handle<JsObject> event) {
230 LocalVar<JsValue> detail =
GetMemberRaw(event,
"detail");
231 client->
OnError(ConvertError(detail));
233 ATTACH(
"error", on_error);
235 const auto on_buffering = [=](Handle<JsObject> event) {
236 LocalVar<JsValue> is_buffering =
GetMemberRaw(event,
"buffering");
237 bool is_buffering_bool;
238 if (
FromJsValue(is_buffering, &is_buffering_bool)) {
241 client->
OnError(
Error(
"Bad 'buffering' event from JavaScript Player"));
244 ATTACH(
"buffering", on_buffering);
247 auto results = CallMethod<Handle<JsObject>>(
"getNetworkingEngine").
get();
248 if (holds_alternative<Error>(results))
249 return get<Error>(results);
251 net_engine.
Init(
get<Handle<JsObject>>(results));
255 std::shared_ptr<Request> pub_request(
new Request(std::move(request)));
256 StepNetworkFilter(type, pub_request, filters_.begin(),
261 net_engine.CallMethod<
void>(
"registerRequestFilter", req_filter).
get();
262 if (holds_alternative<Error>(results2))
263 return get<Error>(results2);
267 std::shared_ptr<Response> pub_response(
new Response(std::move(response)));
268 StepNetworkFilter(type, pub_response, filters_.begin(),
273 net_engine.CallMethod<
void>(
"registerResponseFilter", resp_filter)
275 if (holds_alternative<Error>(results2))
276 return get<Error>(results2);
281 template <
typename T>
283 std::list<NetworkFilters*>::iterator it,
284 filter_member_t<T> on_filter,
Promise results) {
286 std::unique_lock<Mutex> lock(filters_mutex_);
287 for (; it != filters_.end(); it++) {
291 auto future = ((*it)->*on_filter)(type, obj.get());
293 StepNetworkFilter(type, obj, std::next(it), on_filter, results);
307 Mutex filters_mutex_;
308 std::list<NetworkFilters*> filters_;
313 Player::Client::~Client() {}
330 return Impl::CallGlobalMethod<void>({
"shaka",
"log",
"setLevel"},
331 static_cast<int>(level));
336 return Impl::GetGlobalField<Player::LogLevel>(
337 {
"shaka",
"log",
"currentLevel"});
342 return Impl::GetGlobalField<std::string>({
"shaka",
"Player",
"version"});
348 return impl_->Initialize(client, player);
352 return impl_->CallMethod<
void>(
"destroy");
357 return impl_->CallMethod<
bool>(
"isAudioOnly");
361 return impl_->CallMethod<
bool>(
"isBuffering");
365 return impl_->CallMethod<
bool>(
"isInProgress");
369 return impl_->CallMethod<
bool>(
"isLive");
373 return impl_->CallMethod<
bool>(
"isTextTrackVisible");
377 return impl_->CallMethod<
bool>(
"usingEmbeddedTextTrack");
391 return impl_->CallMethod<std::vector<LanguageRole>>(
392 "getAudioLanguagesAndRoles");
396 return impl_->CallMethod<
BufferedInfo>(
"getBufferedInfo");
400 return impl_->CallMethod<
double>(
"getExpiration");
404 return impl_->CallMethod<
Stats>(
"getStats");
408 return impl_->CallMethod<std::vector<Track>>(
"getTextTracks");
412 return impl_->CallMethod<std::vector<Track>>(
"getVariantTracks");
417 return impl_->CallMethod<std::vector<LanguageRole>>(
418 "getTextLanguagesAndRoles");
422 return impl_->CallMethod<std::string>(
"keySystem");
432 const std::string& mime_type) {
433 return impl_->CallMethod<
void>(
"load", manifest_uri, LoadHelper(start_time),
438 return impl_->CallMethod<
void>(
"unload");
443 return impl_->CallMethod<
bool>(
"configure", name_path,
Any());
447 return impl_->CallMethod<
bool>(
"configure", name_path, value);
452 return impl_->CallMethod<
bool>(
"configure", name_path, value);
456 const std::string& value) {
457 return impl_->CallMethod<
bool>(
"configure", name_path, value);
461 return impl_->GetConfigValue<
bool>(name_path);
465 const std::string& name_path) {
466 return impl_->GetConfigValue<
double>(name_path);
470 const std::string& name_path) {
471 return impl_->GetConfigValue<std::string>(name_path);
476 return impl_->CallMethod<
void>(
"resetConfiguration");
480 return impl_->CallMethod<
void>(
"retryStreaming");
485 return impl_->CallMethod<
void>(
"selectAudioLanguage", language, role);
489 return impl_->CallMethod<
void>(
"selectEmbeddedTextTrack");
494 return impl_->CallMethod<
void>(
"selectTextLanguage", language, role);
498 return impl_->CallMethod<
void>(
"selectTextTrack", track.
GetInternal());
503 return impl_->CallMethod<
void>(
"selectVariantTrack", track.
GetInternal(),
508 return impl_->CallMethod<
void>(
"setTextTrackVisibility", visibility);
512 const std::string& language,
513 const std::string& kind,
514 const std::string& mime,
515 const std::string& codec,
516 const std::string& label) {
517 return impl_->CallMethod<
Track>(
"addTextTrack", uri, language, kind, mime,
522 return impl_->Attach(player);
526 return impl_->Detach();
530 impl_->AddNetworkFilters(filters);
534 impl_->RemoveNetworkFilters(filters);
538 const uint8_t* data,
size_t data_size) {
539 return impl_->CallMethod<
bool>(
"configure", name_path,
543 void* Player::GetRawJsValue() {
544 return impl_->GetRawJsValue();
AsyncResults< void > Detach()
Converter< void >::future_type Initialize(Client *client, media::MediaPlayer *player)
AsyncResults< std::string > GetConfigurationString(const std::string &name_path)
AsyncResults< void > SelectTextLanguage(const std::string &language, optional< std::string > role=nullopt)
ReturnVal< JsValue > JsUndefined()
void RemoveNetworkFilters(NetworkFilters *filters)
bool FromJsValue(Handle< JsValue > source, T *dest)
AsyncResults< std::vector< LanguageRole > > GetAudioLanguagesAndRoles() const
ReturnVal< JsValue > GetDescendant(Handle< JsObject > root, const std::vector< std::string > &names)
AsyncResults< BufferedInfo > GetBufferedInfo() const
AsyncResults< bool > IsInProgress() const
AsyncResults< bool > IsBuffering() const
static AsyncResults< LogLevel > GetLogLevel(JsManager *engine)
static AsyncResults< void > SetLogLevel(JsManager *engine, LogLevel level)
ReturnVal< JsValue > ToJsValue(T &&source)
AsyncResults< void > SelectEmbeddedTextTrack()
virtual void OnBuffering(bool is_buffering)
#define SHAKA_NON_COPYABLE_OR_MOVABLE_TYPE(Type)
AsyncResults< double > GetConfigurationDouble(const std::string &name_path)
void HandleNetworkFuture(Promise promise, std::future< optional< Error >> future, std::function< void()> on_done)
AsyncResults< bool > GetConfigurationBool(const std::string &name_path)
AsyncResults< void > RetryStreaming()
virtual std::future< optional< Error > > OnRequestFilter(RequestType type, Request *request)
void RemoveNetworkFilters(NetworkFilters *filters)
AsyncResults< std::string > KeySystem() const
void ResolveWith(Handle< JsValue > value, bool run_events=true)
std::shared_future< impl::RetOf< Func > > InvokeOrSchedule(Func &&callback)
AsyncResults< bool > UsingEmbeddedTextTrack() const
AsyncResults< bool > IsTextTrackVisible() const
AsyncResults< void > Initialize(Client *client, media::MediaPlayer *player=nullptr)
AsyncResults< void > Load(const std::string &manifest_uri, double start_time=NAN, const std::string &mime_type="")
AsyncResults< Track > AddTextTrack(const std::string &uri, const std::string &language, const std::string &kind, const std::string &mime, const std::string &codec="", const std::string &label="")
Converter< T >::future_type GetConfigValue(const std::string &name_path)
virtual void OnError(const Error &error)
proto::ValueType GetValueType(Handle< JsValue > value)
js::Track GetInternal() const
Player(JsManager *engine)
static JsManagerImpl * Instance()
AsyncResults< void > Attach(media::MediaPlayer *player)
Converter< void >::future_type Detach()
AsyncResults< optional< std::string > > AssetUri() const
const char * GetShakaEmbeddedVersion(void)
AsyncResults< void > Destroy()
Converter< void >::future_type Attach(media::MediaPlayer *player)
AsyncResults< std::vector< LanguageRole > > GetTextLanguagesAndRoles() const
static RefPtr< Document > EnsureGlobalDocument()
#define ATTACH(name, call)
AsyncResults< std::vector< Track > > GetTextTracks() const
AsyncResults< void > Unload()
AsyncResults< void > SetTextTrackVisibility(bool visibility)
std::shared_ptr< ThreadEvent< impl::RetOf< Func > > > AddInternalTask(TaskPriority priority, const std::string &name, Func &&callback)
static Promise PendingPromise()
AsyncResults< void > SelectTextTrack(const Track &track)
static bool FromJsValue(Handle< JsValue > source, Player::LogLevel *level)
AsyncResults< bool > Configure(const std::string &name_path, DefaultValueType)
AsyncResults< Stats > GetStats() const
AsyncResults< bool > IsAudioOnly() const
AsyncResults< bool > IsLive() const
std::vector< std::string > StringSplit(const std::string &source, char split_on)
Player & operator=(Player &&)
AsyncResults< BufferedRange > SeekRange() const
AsyncResults< double > GetExpiration() const
void AddNetworkFilters(NetworkFilters *filters)
AsyncResults< void > ResetConfiguration()
AsyncResults< std::vector< Track > > GetVariantTracks() const
bool InvokeConstructor(Handle< JsFunction > ctor, int argc, LocalVar< JsValue > *argv, LocalVar< JsValue > *result_or_except)
AsyncResults< void > SelectAudioLanguage(const std::string &language, optional< std::string > role=nullopt)
void Init(Handle< JsObject > object)
ReturnVal< JsValue > GetMemberRaw(Handle< JsObject > object, const std::string &name, LocalVar< JsValue > *exception=nullptr)
static AsyncResults< std::string > GetPlayerVersion(JsManager *engine)
void AddNetworkFilters(NetworkFilters *filters)
AsyncResults< void > SelectVariantTrack(const Track &track, bool clear_buffer=false)
#define SHAKA_VERSION_STR
AsyncResults< optional< DrmInfo > > DrmInfo() const
virtual std::future< optional< Error > > OnResponseFilter(RequestType type, Response *response)
TaskRunner * MainThread()