Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/media/media_internals.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/strings/string16.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "content/public/browser/web_ui.h"
     12 #include "media/base/media_log.h"
     13 #include "media/base/media_log_event.h"
     14 
     15 namespace content {
     16 
     17 MediaInternals* MediaInternals::GetInstance() {
     18   return Singleton<MediaInternals>::get();
     19 }
     20 
     21 MediaInternals::~MediaInternals() {}
     22 
     23 void MediaInternals::OnDeleteAudioStream(void* host, int stream_id) {
     24   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     25   std::string stream = base::StringPrintf("audio_streams.%p:%d",
     26                                           host, stream_id);
     27   DeleteItem(stream);
     28 }
     29 
     30 void MediaInternals::OnSetAudioStreamPlaying(
     31     void* host, int stream_id, bool playing) {
     32   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     33   UpdateAudioStream(host, stream_id,
     34                     "playing", new base::FundamentalValue(playing));
     35 }
     36 
     37 void MediaInternals::OnSetAudioStreamStatus(
     38     void* host, int stream_id, const std::string& status) {
     39   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     40   UpdateAudioStream(host, stream_id,
     41                     "status", new base::StringValue(status));
     42 }
     43 
     44 void MediaInternals::OnSetAudioStreamVolume(
     45     void* host, int stream_id, double volume) {
     46   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     47   UpdateAudioStream(host, stream_id,
     48                     "volume", new base::FundamentalValue(volume));
     49 }
     50 
     51 void MediaInternals::OnMediaEvents(
     52     int render_process_id, const std::vector<media::MediaLogEvent>& events) {
     53   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     54 
     55   // Notify observers that |event| has occured.
     56   for (std::vector<media::MediaLogEvent>::const_iterator event = events.begin();
     57       event != events.end(); ++event) {
     58     base::DictionaryValue dict;
     59     dict.SetInteger("renderer", render_process_id);
     60     dict.SetInteger("player", event->id);
     61     dict.SetString("type", media::MediaLog::EventTypeToString(event->type));
     62 
     63     int64 ticks = event->time.ToInternalValue();
     64     double ticks_millis =
     65         ticks / static_cast<double>(base::Time::kMicrosecondsPerMillisecond);
     66 
     67     dict.SetDouble("ticksMillis", ticks_millis);
     68     dict.Set("params", event->params.DeepCopy());
     69     SendUpdate("media.onMediaEvent", &dict);
     70   }
     71 }
     72 
     73 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
     74   update_callbacks_.push_back(callback);
     75 }
     76 
     77 void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
     78   for (size_t i = 0; i < update_callbacks_.size(); ++i) {
     79     if (update_callbacks_[i].Equals(callback)) {
     80       update_callbacks_.erase(update_callbacks_.begin() + i);
     81       return;
     82     }
     83   }
     84   NOTREACHED();
     85 }
     86 
     87 void MediaInternals::SendEverything() {
     88   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     89   SendUpdate("media.onReceiveEverything", &data_);
     90 }
     91 
     92 MediaInternals::MediaInternals() {
     93 }
     94 
     95 void MediaInternals::UpdateAudioStream(void* host,
     96                                        int stream_id,
     97                                        const std::string& property,
     98                                        base::Value* value) {
     99   std::string stream = base::StringPrintf("audio_streams.%p:%d",
    100                                           host, stream_id);
    101   UpdateItem("media.addAudioStream", stream, property, value);
    102 }
    103 
    104 void MediaInternals::DeleteItem(const std::string& item) {
    105   data_.Remove(item, NULL);
    106   scoped_ptr<base::Value> value(new base::StringValue(item));
    107   SendUpdate("media.onItemDeleted", value.get());
    108 }
    109 
    110 void MediaInternals::UpdateItem(
    111     const std::string& update_fn, const std::string& id,
    112     const std::string& property, base::Value* value) {
    113   base::DictionaryValue* item_properties;
    114   if (!data_.GetDictionary(id, &item_properties)) {
    115     item_properties = new base::DictionaryValue();
    116     data_.Set(id, item_properties);
    117     item_properties->SetString("id", id);
    118   }
    119   item_properties->Set(property, value);
    120   SendUpdate(update_fn, item_properties);
    121 }
    122 
    123 void MediaInternals::SendUpdate(const std::string& function,
    124                                 base::Value* value) {
    125   // Only bother serializing the update to JSON if someone is watching.
    126   if (update_callbacks_.empty())
    127     return;
    128 
    129   std::vector<const base::Value*> args;
    130   args.push_back(value);
    131   string16 update = WebUI::GetJavascriptCall(function, args);
    132   for (size_t i = 0; i < update_callbacks_.size(); i++)
    133     update_callbacks_[i].Run(update);
    134 }
    135 
    136 }  // namespace content
    137