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