12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/media_internals.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_log.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_log_event.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaInternals* MediaInternals::GetInstance() {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Singleton<MediaInternals>::get();
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaInternals::~MediaInternals() {}
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::OnDeleteAudioStream(void* host, int stream_id) {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string stream = base::StringPrintf("audio_streams.%p:%d",
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          host, stream_id);
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeleteItem(stream);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::OnSetAudioStreamPlaying(
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* host, int stream_id, bool playing) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAudioStream(host, stream_id,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    "playing", new base::FundamentalValue(playing));
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::OnSetAudioStreamStatus(
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* host, int stream_id, const std::string& status) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAudioStream(host, stream_id,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    "status", new base::StringValue(status));
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::OnSetAudioStreamVolume(
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* host, int stream_id, double volume) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAudioStream(host, stream_id,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    "volume", new base::FundamentalValue(volume));
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaInternals::OnMediaEvents(
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int render_process_id, const std::vector<media::MediaLogEvent>& events) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify observers that |event| has occured.
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<media::MediaLogEvent>::const_iterator event = events.begin();
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      event != events.end(); ++event) {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue dict;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetInteger("renderer", render_process_id);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetInteger("player", event->id);
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetString("type", media::MediaLog::EventTypeToString(event->type));
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 ticks = event->time.ToInternalValue();
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    double ticks_millis =
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        ticks / static_cast<double>(base::Time::kMicrosecondsPerMillisecond);
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict.SetDouble("ticksMillis", ticks_millis);
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.Set("params", event->params.DeepCopy());
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendUpdate("media.onMediaEvent", &dict);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  update_callbacks_.push_back(callback);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < update_callbacks_.size(); ++i) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (update_callbacks_[i].Equals(callback)) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update_callbacks_.erase(update_callbacks_.begin() + i);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::SendEverything() {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendUpdate("media.onReceiveEverything", &data_);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaInternals::MediaInternals() {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::UpdateAudioStream(void* host,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int stream_id,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& property,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::Value* value) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string stream = base::StringPrintf("audio_streams.%p:%d",
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          host, stream_id);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateItem("media.addAudioStream", stream, property, value);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::DeleteItem(const std::string& item) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data_.Remove(item, NULL);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value(new base::StringValue(item));
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendUpdate("media.onItemDeleted", value.get());
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::UpdateItem(
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& update_fn, const std::string& id,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& property, base::Value* value) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* item_properties;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data_.GetDictionary(id, &item_properties)) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    item_properties = new base::DictionaryValue();
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_.Set(id, item_properties);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    item_properties->SetString("id", id);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  item_properties->Set(property, value);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendUpdate(update_fn, item_properties);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::SendUpdate(const std::string& function,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base::Value* value) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only bother serializing the update to JSON if someone is watching.
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (update_callbacks_.empty())
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<const base::Value*> args;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.push_back(value);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 update = WebUI::GetJavascriptCall(function, args);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < update_callbacks_.size(); i++)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_callbacks_[i].Run(update);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
137