summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordhg@chromium.org <dhg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 19:48:23 +0000
committerdhg@chromium.org <dhg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 19:48:23 +0000
commit17496bbed312152a6a0c2251c88ccefd70849540 (patch)
tree03edf49985ed65b6e42d2385566d600fd88f2535 /chrome
parenta0607da9446e3ec76a7ced32502f8c7e71654d53 (diff)
downloadchromium_src-17496bbed312152a6a0c2251c88ccefd70849540.zip
chromium_src-17496bbed312152a6a0c2251c88ccefd70849540.tar.gz
chromium_src-17496bbed312152a6a0c2251c88ccefd70849540.tar.bz2
Adding initial version of the mediaplayer. This only hooks into the system if the user selects a file via the filebrowser.
BUG=none TEST=none Review URL: http://codereview.chromium.org/749001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41191 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/theme/mediaplayer_menu.pngbin0 -> 578 bytes
-rw-r--r--chrome/app/theme/mediaplayer_next.pngbin0 -> 902 bytes
-rw-r--r--chrome/app/theme/mediaplayer_pause.pngbin0 -> 403 bytes
-rw-r--r--chrome/app/theme/mediaplayer_play.pngbin0 -> 536 bytes
-rw-r--r--chrome/app/theme/mediaplayer_prev.pngbin0 -> 941 bytes
-rw-r--r--chrome/app/theme/mediaplayer_vol_high.pngbin0 -> 1005 bytes
-rw-r--r--chrome/app/theme/theme_resources.grd6
-rw-r--r--chrome/browser/browser_init.cc3
-rw-r--r--chrome/browser/browser_resources.grd2
-rw-r--r--chrome/browser/dom_ui/dom_ui_factory.cc4
-rw-r--r--chrome/browser/dom_ui/filebrowse_ui.cc30
-rw-r--r--chrome/browser/dom_ui/mediaplayer_ui.cc528
-rw-r--r--chrome/browser/dom_ui/mediaplayer_ui.h80
-rw-r--r--chrome/browser/resources/filebrowse.html4
-rw-r--r--chrome/browser/resources/mediaplayer.html618
-rw-r--r--chrome/browser/resources/playlist.html120
-rwxr-xr-xchrome/chrome_browser.gypi2
-rw-r--r--chrome/common/url_constants.cc2
-rw-r--r--chrome/common/url_constants.h2
19 files changed, 1399 insertions, 2 deletions
diff --git a/chrome/app/theme/mediaplayer_menu.png b/chrome/app/theme/mediaplayer_menu.png
new file mode 100644
index 0000000..a8e3b90
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_menu.png
Binary files differ
diff --git a/chrome/app/theme/mediaplayer_next.png b/chrome/app/theme/mediaplayer_next.png
new file mode 100644
index 0000000..f8af798
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_next.png
Binary files differ
diff --git a/chrome/app/theme/mediaplayer_pause.png b/chrome/app/theme/mediaplayer_pause.png
new file mode 100644
index 0000000..c874205
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_pause.png
Binary files differ
diff --git a/chrome/app/theme/mediaplayer_play.png b/chrome/app/theme/mediaplayer_play.png
new file mode 100644
index 0000000..a1aaf8e
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_play.png
Binary files differ
diff --git a/chrome/app/theme/mediaplayer_prev.png b/chrome/app/theme/mediaplayer_prev.png
new file mode 100644
index 0000000..ff38633
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_prev.png
Binary files differ
diff --git a/chrome/app/theme/mediaplayer_vol_high.png b/chrome/app/theme/mediaplayer_vol_high.png
new file mode 100644
index 0000000..067a56c
--- /dev/null
+++ b/chrome/app/theme/mediaplayer_vol_high.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 1206f72..e3d59ee 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -440,6 +440,12 @@
<include name="IDR_FILEBROWSER_UPLOAD" file="filebrowse_upload.png" type="BINDATA" />
<include name="IDR_FILEBROWSER_FULLSCREEN" file="filebrowse_fullscreen.png" type="BINDATA" />
<include name="IDR_FILEBROWSER_MENU" file="filebrowse_menu.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_PLAY" file="mediaplayer_play.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_PAUSE" file="mediaplayer_pause.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_NEXT" file="mediaplayer_next.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_PREV" file="mediaplayer_prev.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_MENU" file="mediaplayer_menu.png" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_VOL_HIGH" file="mediaplayer_vol_high.png" type="BINDATA" />
</if>
<if expr="(pp_ifdef('chromeos') or pp_ifdef('toolkit_views')) and pp_ifdef('_google_chrome')">
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index 9f92ad8..8481acf 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -61,6 +61,7 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/browser_notification_observers.h"
+#include "chrome/browser/dom_ui/mediaplayer_ui.h"
#include "chrome/browser/chromeos/cros/mount_library.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
#include "chrome/browser/chromeos/usb_mount_observer.h"
@@ -386,6 +387,8 @@ bool BrowserInit::LaunchBrowser(
// and have the constructor take care of everything else.
chromeos::MountLibrary* lib = chromeos::MountLibrary::Get();
chromeos::USBMountObserver* observe = chromeos::USBMountObserver::Get();
+ MediaPlayer* player = MediaPlayer::Get();
+ player->set_profile(profile);
observe->set_profile(profile);
lib->AddObserver(observe);
}
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 9ce3355..22d06ba 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -41,6 +41,8 @@ without changes to the corresponding grd file. tea -->
<if expr="pp_ifdef('chromeos') or pp_ifdef('toolkit_views')">
<include name="IDR_FILEBROWSE_HTML" file="resources\filebrowse.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_OS_CREDITS_HTML" file="resources\about_os_credits.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYER_HTML" file="resources\mediaplayer.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MEDIAPLAYERPLAYLIST_HTML" file="resources\playlist.html" flattenhtml="true" type="BINDATA" />
</if>
<include name="IDR_BOOKMARKS_MANIFEST" file="resources\bookmark_manager\manifest.json" type="BINDATA" />
<include name="IDR_DOWNLOADS_HTML" file="resources\downloads.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc
index 3e584e3..86f78c5 100644
--- a/chrome/browser/dom_ui/dom_ui_factory.cc
+++ b/chrome/browser/dom_ui/dom_ui_factory.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/dom_ui/history_ui.h"
#include "chrome/browser/dom_ui/filebrowse_ui.h"
#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/mediaplayer_ui.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/dom_ui/print_ui.h"
#include "chrome/browser/extensions/extension_dom_ui.h"
@@ -98,6 +99,9 @@ static DOMUIFactoryFunction GetDOMUIFactoryFunction(const GURL& url) {
#if defined(OS_CHROMEOS)
if (url.host() == chrome::kChromeUIFileBrowseHost)
return &NewDOMUI<FileBrowseUI>;
+
+ if (url.host() == chrome::kChromeUIMediaplayerHost)
+ return &NewDOMUI<MediaplayerUI>;
#endif
return NULL;
diff --git a/chrome/browser/dom_ui/filebrowse_ui.cc b/chrome/browser/dom_ui/filebrowse_ui.cc
index a1b56d9..100124e 100644
--- a/chrome/browser/dom_ui/filebrowse_ui.cc
+++ b/chrome/browser/dom_ui/filebrowse_ui.cc
@@ -34,6 +34,7 @@
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
+#include "chrome/browser/dom_ui/mediaplayer_ui.h"
#include "net/base/escape.h"
#include "grit/browser_resources.h"
@@ -156,6 +157,8 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
void HandleCreateNewFolder(const Value* value);
+ void PlayMediaFile(const Value* value);
+
void HandleDeleteFile(const Value* value);
void DeleteFile(const FilePath& path);
void FireDeleteComplete(const FilePath& path);
@@ -358,6 +361,8 @@ void FilebrowseHandler::RegisterMessages() {
NewCallback(this, &FilebrowseHandler::HandleGetDownloads));
dom_ui_->RegisterMessageCallback("createNewFolder",
NewCallback(this, &FilebrowseHandler::HandleCreateNewFolder));
+ dom_ui_->RegisterMessageCallback("playMediaFile",
+ NewCallback(this, &FilebrowseHandler::PlayMediaFile));
dom_ui_->RegisterMessageCallback("pauseToggleDownload",
NewCallback(this, &FilebrowseHandler::HandlePauseToggleDownload));
dom_ui_->RegisterMessageCallback("deleteFile",
@@ -498,6 +503,31 @@ void FilebrowseHandler::HandleCreateNewFolder(const Value* value) {
#endif
}
+void FilebrowseHandler::PlayMediaFile(const Value* value) {
+#if defined(OS_CHROMEOS)
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ std::string path;
+
+ // Get path string.
+ if (list_value->GetString(0, &path)) {
+ FilePath currentpath;
+ currentpath = FilePath(path);
+
+ MediaPlayer* mediaplayer = MediaPlayer::Get();
+ std::string url = currentpath.value();
+
+ GURL gurl(url);
+
+ mediaplayer->EnqueueMediaURL(gurl);
+ } else {
+ LOG(ERROR) << "Unable to get string";
+ return;
+ }
+ }
+#endif
+}
+
void FilebrowseHandler::HandleRefreshDirectory(const Value* value) {
if (value && value->GetType() == Value::TYPE_LIST) {
const ListValue* list_value = static_cast<const ListValue*>(value);
diff --git a/chrome/browser/dom_ui/mediaplayer_ui.cc b/chrome/browser/dom_ui/mediaplayer_ui.cc
new file mode 100644
index 0000000..1feeef6
--- /dev/null
+++ b/chrome/browser/dom_ui/mediaplayer_ui.cc
@@ -0,0 +1,528 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/dom_ui/mediaplayer_ui.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/singleton.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/thread.h"
+#include "base/time.h"
+#include "base/values.h"
+#include "base/weak_ptr.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/url_fetcher.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/time_format.h"
+#include "chrome/common/url_constants.h"
+#include "net/base/escape.h"
+
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+
+static const std::wstring kPropertyPath = L"path";
+static const std::wstring kPropertyForce = L"force";
+static const std::wstring kPropertyTitle = L"title";
+static const std::wstring kPropertyOffset = L"currentOffset";
+
+const char* kMediaplayerURL = "chrome://mediaplayer";
+const char* kMediaplayerPlaylistURL = "chrome://mediaplayer#playlist";
+const int kPopupLeft = 0;
+const int kPopupTop = 0;
+const int kPopupWidth = 350;
+const int kPopupHeight = 300;
+
+class MediaplayerUIHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+ explicit MediaplayerUIHTMLSource(bool is_playlist);
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path,
+ bool is_off_the_record,
+ int request_id);
+ virtual std::string GetMimeType(const std::string&) const {
+ return "text/html";
+ }
+
+ private:
+ ~MediaplayerUIHTMLSource() {}
+ bool is_playlist_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaplayerUIHTMLSource);
+};
+
+// The handler for Javascript messages related to the "mediaplayer" view.
+class MediaplayerHandler : public DOMMessageHandler,
+ public base::SupportsWeakPtr<MediaplayerHandler> {
+ public:
+ explicit MediaplayerHandler(bool is_playlist);
+ virtual ~MediaplayerHandler();
+
+ // Init work after Attach.
+ void Init(bool is_playlist, TabContents* contents);
+
+ // DOMMessageHandler implementation.
+ virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+ virtual void RegisterMessages();
+
+ // Callback for the "currentOffsetChanged" message.
+ void HandleCurrentOffsetChanged(const Value* value);
+
+ void PlaybackMediaFile(const GURL& url);
+
+ void EnqueueMediaFile(const GURL& url);
+
+ void GetPlaylistValue(ListValue& value);
+
+ // Callback for the "playbackError" message.
+ void HandlePlaybackError(const Value* value);
+
+ // Callback for the "getCurrentPlaylist" message.
+ void HandleGetCurrentPlaylist(const Value* value);
+
+ void HandleTogglePlaylist(const Value* value);
+ void HandleSetCurrentPlaylistOffset(const Value* value);
+
+ const std::vector<GURL>& GetCurrentPlaylist();
+
+ int GetCurrentPlaylistOffset();
+ void SetCurrentPlaylistOffset(int offset);
+ // Used to set the playlist for playlist views, since the playlist is
+ // maintained by the mediaplayer itself.
+ void SetCurrentPlaylist(const std::vector<GURL>& playlist, int offset);
+
+ private:
+
+ Profile* profile_;
+ std::vector<GURL> currentPlaylist_;
+ int currentOffset_;
+ bool is_playlist_;
+ DISALLOW_COPY_AND_ASSIGN(MediaplayerHandler);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// MediaplayerHTMLSource
+//
+////////////////////////////////////////////////////////////////////////////////
+
+MediaplayerUIHTMLSource::MediaplayerUIHTMLSource(bool is_playlist)
+ : DataSource(chrome::kChromeUIMediaplayerHost, MessageLoop::current()) {
+ is_playlist_ = is_playlist;
+}
+
+void MediaplayerUIHTMLSource::StartDataRequest(const std::string& path,
+ bool is_off_the_record, int request_id) {
+ DictionaryValue localized_strings;
+ // TODO(dhg): Add stirings to localized strings, also add more strings
+ // that are currently hardcoded.
+ localized_strings.SetString(L"devices", "devices");
+
+ SetFontAndTextDirection(&localized_strings);
+
+ std::string full_html;
+
+ static const base::StringPiece mediaplayer_html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_MEDIAPLAYER_HTML));
+
+ static const base::StringPiece playlist_html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_MEDIAPLAYERPLAYLIST_HTML));
+
+ if (is_playlist_) {
+ full_html = jstemplate_builder::GetI18nTemplateHtml(
+ playlist_html, &localized_strings);
+ } else {
+ full_html = jstemplate_builder::GetI18nTemplateHtml(
+ mediaplayer_html, &localized_strings);
+ }
+
+ scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+ html_bytes->data.resize(full_html.size());
+ std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
+
+ SendResponse(request_id, html_bytes);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// MediaplayerHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+MediaplayerHandler::MediaplayerHandler(bool is_playlist)
+ : profile_(NULL),
+ currentOffset_(0),
+ is_playlist_(is_playlist) {
+}
+
+MediaplayerHandler::~MediaplayerHandler() {
+}
+
+DOMMessageHandler* MediaplayerHandler::Attach(DOMUI* dom_ui) {
+ // Create our favicon data source.
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ Singleton<ChromeURLDataManager>::get(),
+ &ChromeURLDataManager::AddDataSource,
+ make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
+ profile_ = dom_ui->GetProfile();
+
+ return DOMMessageHandler::Attach(dom_ui);
+}
+
+void MediaplayerHandler::Init(bool is_playlist, TabContents* contents) {
+ MediaPlayer* player = MediaPlayer::Get();
+ if (!is_playlist) {
+ player->RegisterNewHandler(this, contents);
+ } else {
+ player->RegisterNewPlaylistHandler(this, contents);
+ }
+}
+
+void MediaplayerHandler::RegisterMessages() {
+ dom_ui_->RegisterMessageCallback("currentOffsetChanged",
+ NewCallback(this, &MediaplayerHandler::HandleCurrentOffsetChanged));
+ dom_ui_->RegisterMessageCallback("playbackError",
+ NewCallback(this, &MediaplayerHandler::HandlePlaybackError));
+ dom_ui_->RegisterMessageCallback("getCurrentPlaylist",
+ NewCallback(this, &MediaplayerHandler::HandleGetCurrentPlaylist));
+ dom_ui_->RegisterMessageCallback("togglePlaylist",
+ NewCallback(this, &MediaplayerHandler::HandleTogglePlaylist));
+ dom_ui_->RegisterMessageCallback("setCurrentPlaylistOffset",
+ NewCallback(this, &MediaplayerHandler::HandleSetCurrentPlaylistOffset));
+}
+
+void MediaplayerHandler::GetPlaylistValue(ListValue& value) {
+ for (unsigned int x = 0; x < currentPlaylist_.size(); x++) {
+ DictionaryValue* url_value = new DictionaryValue();
+ url_value->SetString(kPropertyPath, currentPlaylist_[x].spec());
+ value.Append(url_value);
+ }
+}
+
+void MediaplayerHandler::PlaybackMediaFile(const GURL& url) {
+ GURL newurl(url);
+ currentPlaylist_.clear();
+ currentPlaylist_.push_back(newurl);
+
+ DictionaryValue info_value;
+ ListValue urls;
+ GetPlaylistValue(urls);
+ info_value.SetBoolean(kPropertyForce, true);
+ info_value.SetString(kPropertyPath, newurl.spec());
+ dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+ MediaPlayer::Get()->NotifyPlaylistChanged();
+}
+
+const std::vector<GURL>& MediaplayerHandler::GetCurrentPlaylist() {
+ return currentPlaylist_;
+}
+
+int MediaplayerHandler::GetCurrentPlaylistOffset() {
+ return currentOffset_;
+}
+
+void MediaplayerHandler::HandleSetCurrentPlaylistOffset(const Value* value) {
+ ListValue results_value;
+ DictionaryValue info_value;
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ std::string val;
+
+ // Get the new playlist offset;
+ if (list_value->GetString(0, &val)) {
+ int id = atoi(val.c_str());
+ MediaPlayer::Get()->SetPlaylistOffset(id);
+ }
+ }
+}
+
+void MediaplayerHandler::SetCurrentPlaylistOffset(int offset) {
+ currentOffset_ = offset;
+ DictionaryValue info_value;
+ ListValue urls;
+ GetPlaylistValue(urls);
+ info_value.SetString(kPropertyPath, "");
+ info_value.SetBoolean(kPropertyForce, true);
+ info_value.SetInteger(kPropertyOffset, currentOffset_);
+ dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+}
+
+void MediaplayerHandler::SetCurrentPlaylist(const std::vector<GURL>& playlist,
+ int offset) {
+ currentPlaylist_ = playlist;
+ currentOffset_ = offset;
+ DictionaryValue info_value;
+ ListValue urls;
+ GetPlaylistValue(urls);
+ info_value.SetString(kPropertyPath, "");
+ info_value.SetBoolean(kPropertyForce, false);
+ info_value.SetInteger(kPropertyOffset, currentOffset_);
+ dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+}
+
+void MediaplayerHandler::EnqueueMediaFile(const GURL& url) {
+ GURL newurl(url);
+ currentPlaylist_.push_back(newurl);
+ DictionaryValue info_value;
+ ListValue urls;
+ GetPlaylistValue(urls);
+ info_value.SetString(kPropertyPath, newurl.spec());
+ info_value.SetBoolean(kPropertyForce, false);
+ info_value.SetInteger(kPropertyOffset, currentOffset_);
+ dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+ MediaPlayer::Get()->NotifyPlaylistChanged();
+}
+
+void MediaplayerHandler::HandleCurrentOffsetChanged(const Value* value) {
+ ListValue results_value;
+ DictionaryValue info_value;
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ std::string val;
+
+ // Get the new playlist offset;
+ if (list_value->GetString(0, &val)) {
+ int id = atoi(val.c_str());
+ currentOffset_ = id;
+ MediaPlayer::Get()->NotifyPlaylistChanged();
+ }
+ }
+}
+
+void MediaplayerHandler::HandlePlaybackError(const Value* value) {
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ std::string error;
+
+ // Get path string.
+ if (list_value->GetString(0, &error)) {
+ LOG(ERROR) << "Playback error" << error;
+ }
+ }
+}
+
+void MediaplayerHandler::HandleGetCurrentPlaylist(const Value* value) {
+ DictionaryValue info_value;
+ ListValue urls;
+ GetPlaylistValue(urls);
+ info_value.SetInteger(kPropertyOffset, currentOffset_);
+ dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+}
+
+void MediaplayerHandler::HandleTogglePlaylist(const Value* value) {
+ MediaPlayer::Get()->TogglePlaylistWindowVisible();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Mediaplayer
+//
+////////////////////////////////////////////////////////////////////////////////
+
+void MediaPlayer::EnqueueMediaURL(const GURL& url) {
+ if (handler_ == NULL) {
+ GURL newurl(url);
+ unhandled_urls_.push_back(url);
+ PopupMediaPlayer();
+ } else {
+ handler_->EnqueueMediaFile(url);
+ }
+}
+
+void MediaPlayer::ForcePlayMediaURL(const GURL& url) {
+ if (handler_ == NULL) {
+ GURL newurl(url);
+ unhandled_urls_.push_back(url);
+ PopupMediaPlayer();
+ } else {
+ handler_->PlaybackMediaFile(url);
+ }
+}
+
+void MediaPlayer::TogglePlaylistWindowVisible() {
+ if (playlist_browser_) {
+ ClosePlaylistWindow();
+ } else {
+ ShowPlaylistWindow();
+ }
+}
+
+void MediaPlayer::ShowPlaylistWindow() {
+ if (playlist_browser_ == NULL) {
+ PopupPlaylist();
+ }
+}
+
+void MediaPlayer::ClosePlaylistWindow() {
+ if (playlist_browser_ != NULL) {
+ playlist_browser_->window()->Close();
+ }
+}
+
+void MediaPlayer::SetPlaylistOffset(int offset) {
+ if (handler_) {
+ handler_->SetCurrentPlaylistOffset(offset);
+ }
+ if (playlist_) {
+ playlist_->SetCurrentPlaylistOffset(offset);
+ }
+}
+
+void MediaPlayer::RegisterNewHandler(MediaplayerHandler* handler,
+ TabContents* contents) {
+ handler_ = handler;
+ mediaplayer_tab_ = contents;
+ RegisterListeners();
+ if (unhandled_urls_.size() != 0) {
+ for (unsigned int x = 0; x < unhandled_urls_.size(); x++) {
+ handler_->EnqueueMediaFile(unhandled_urls_[x]);
+ }
+ unhandled_urls_.clear();
+ }
+}
+
+void MediaPlayer::RegisterListeners() {
+ registrar_.RemoveAll();
+ if (playlist_tab_) {
+ registrar_.Add(this,
+ NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(playlist_tab_));
+ }
+ if (mediaplayer_tab_) {
+ registrar_.Add(this,
+ NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(mediaplayer_tab_));
+ }
+};
+
+void MediaPlayer::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
+ if (Source<TabContents>(source).ptr() == mediaplayer_tab_) {
+ RemoveHandler(handler_);
+ RegisterListeners();
+ ClosePlaylistWindow();
+ } else if (Source<TabContents>(source).ptr() == playlist_tab_) {
+ RemovePlaylistHandler(playlist_);
+ RegisterListeners();
+ }
+}
+
+void MediaPlayer::RegisterNewPlaylistHandler(
+ MediaplayerHandler* handler, TabContents* contents) {
+ playlist_ = handler;
+ playlist_tab_ = contents;
+ RegisterListeners();
+ NotifyPlaylistChanged();
+}
+
+void MediaPlayer::RemovePlaylistHandler(MediaplayerHandler* handler) {
+ if (handler == playlist_) {
+ playlist_ = NULL;
+ playlist_browser_ = NULL;
+ playlist_tab_ = NULL;
+ }
+}
+
+void MediaPlayer::NotifyPlaylistChanged() {
+ if (handler_ && playlist_) {
+ playlist_->SetCurrentPlaylist(handler_->GetCurrentPlaylist(),
+ handler_->GetCurrentPlaylistOffset());
+ }
+}
+
+void MediaPlayer::RemoveHandler(MediaplayerHandler* handler) {
+ if (handler == handler_) {
+ handler_ = NULL;
+ mediaplayer_browser_ = NULL;
+ mediaplayer_tab_ = NULL;
+ }
+}
+
+void MediaPlayer::PopupPlaylist() {
+ playlist_browser_ = Browser::CreateForPopup(profile_);
+ playlist_browser_->AddTabWithURL(
+ GURL(kMediaplayerPlaylistURL), GURL(), PageTransition::LINK,
+ true, -1, false, NULL);
+ playlist_browser_->window()->SetBounds(gfx::Rect(kPopupLeft,
+ kPopupTop,
+ kPopupWidth,
+ kPopupHeight),
+ BrowserWindow::WINDOW_BOUNDS);
+ playlist_browser_->window()->Show();
+};
+
+void MediaPlayer::PopupMediaPlayer() {
+ mediaplayer_browser_ = Browser::CreateForPopup(profile_);
+ mediaplayer_browser_->AddTabWithURL(
+ GURL(kMediaplayerURL), GURL(), PageTransition::LINK,
+ true, -1, false, NULL);
+ mediaplayer_browser_->window()->SetBounds(gfx::Rect(kPopupLeft,
+ kPopupTop,
+ kPopupWidth,
+ kPopupHeight),
+ BrowserWindow::WINDOW_BOUNDS);
+ mediaplayer_browser_->window()->Show();
+};
+
+MediaPlayer::MediaPlayer()
+ : handler_(NULL),
+ playlist_(NULL),
+ playlist_browser_(NULL),
+ mediaplayer_browser_(NULL),
+ mediaplayer_tab_(NULL),
+ playlist_tab_(NULL) {
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// MediaplayerUIContents
+//
+////////////////////////////////////////////////////////////////////////////////
+
+MediaplayerUI::MediaplayerUI(TabContents* contents) : DOMUI(contents) {
+ const GURL& url = contents->GetURL();
+ bool is_playlist = (url.ref() == "playlist");
+ MediaplayerHandler* handler = new MediaplayerHandler(is_playlist);
+ AddMessageHandler((handler)->Attach(this));
+ if (is_playlist) {
+ handler->Init(true, contents);
+ } else {
+ handler->Init(false, contents);
+ }
+
+ MediaplayerUIHTMLSource* html_source =
+ new MediaplayerUIHTMLSource(is_playlist);
+
+ // Set up the chrome://mediaplayer/ source.
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ Singleton<ChromeURLDataManager>::get(),
+ &ChromeURLDataManager::AddDataSource,
+ make_scoped_refptr(html_source)));
+}
diff --git a/chrome/browser/dom_ui/mediaplayer_ui.h b/chrome/browser/dom_ui/mediaplayer_ui.h
new file mode 100644
index 0000000..9a1ce87
--- /dev/null
+++ b/chrome/browser/dom_ui/mediaplayer_ui.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_MEDIAPLAYER_UI_H_
+#define CHROME_BROWSER_DOM_UI_MEDIAPLAYER_UI_H_
+
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "base/values.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/notification_registrar.h"
+#include "net/base/directory_lister.h"
+
+class GURL;
+class MediaplayerHandler;
+class Browser;
+
+class MediaPlayer : public NotificationObserver {
+ public:
+ ~MediaPlayer() {}
+ void EnqueueMediaURL(const GURL& url);
+ void ForcePlayMediaURL(const GURL& url);
+ void TogglePlaylistWindowVisible();
+ void ShowPlaylistWindow();
+ void ClosePlaylistWindow();
+ void SetPlaylistOffset(int offset);
+ void RegisterNewHandler(MediaplayerHandler* handler,
+ TabContents* contents);
+ void RemoveHandler(MediaplayerHandler* handler);
+ void RegisterNewPlaylistHandler(MediaplayerHandler* handler,
+ TabContents* contents);
+ void RemovePlaylistHandler(MediaplayerHandler* handler);
+ void NotifyPlaylistChanged();
+
+ // Used to detect when the mediaplayer is closed
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ static MediaPlayer* Get() {
+ return Singleton<MediaPlayer>::get();
+ }
+ void set_profile(Profile* profile) { profile_ = profile; }
+
+ private:
+ MediaPlayer();
+ void PopupMediaPlayer();
+ void PopupPlaylist();
+ void RegisterListeners();
+
+ Profile* profile_;
+ MediaplayerHandler* handler_;
+ MediaplayerHandler* playlist_;
+ Browser* playlist_browser_;
+ Browser* mediaplayer_browser_;
+ std::vector<GURL> unhandled_urls_;
+ NotificationRegistrar registrar_;
+ TabContents* mediaplayer_tab_;
+ TabContents* playlist_tab_;
+ friend struct DefaultSingletonTraits<MediaPlayer>;
+ DISALLOW_COPY_AND_ASSIGN(MediaPlayer);
+};
+
+class MediaplayerUI : public DOMUI {
+ public:
+ explicit MediaplayerUI(TabContents* contents);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MediaplayerUI);
+};
+
+#endif // CHROME_BROWSER_DOM_UI_MEDIAPLAYER_UI_H_
diff --git a/chrome/browser/resources/filebrowse.html b/chrome/browser/resources/filebrowse.html
index 4ebbe325..095bb2d 100644
--- a/chrome/browser/resources/filebrowse.html
+++ b/chrome/browser/resources/filebrowse.html
@@ -1190,8 +1190,8 @@ function playMediaFile(path) {
videoPlaybackElement.src = 'file://' + path;
}
} else {
- var newPath = 'chrome://filebrowse#' + path;
- chrome.send('openNewPopupWindow', [newPath]);
+ var newPath = 'file://' + path;
+ chrome.send('playMediaFile', [newPath]);
}
};
diff --git a/chrome/browser/resources/mediaplayer.html b/chrome/browser/resources/mediaplayer.html
new file mode 100644
index 0000000..d03c138
--- /dev/null
+++ b/chrome/browser/resources/mediaplayer.html
@@ -0,0 +1,618 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<meta charset="utf-8">
+<title>Media Player</title>
+<style type="text/css">
+.audio.progress {
+ -webkit-appearance: slider-horizontal;
+ position: absolute;
+ left: 93px;
+ right:90px;
+ bottom:-2px;
+ height: 30px;
+}
+
+body {
+ overflow:hidden;
+ background:black;
+}
+
+.video.progress {
+ -webkit-appearance: slider-horizontal;
+ position: absolute;
+ left: 93px;
+ right:90px;
+ bottom:-2px;
+ height: 30px;
+}
+
+.videocontrols {
+ bottom: 0;
+ left: 0;
+ z-index:999;
+ height: 30px;
+ right: 0;
+ position:absolute;
+ background: -webkit-gradient(linear,
+ left top,
+ left bottom,
+ from(#323232),
+ to(#070707));
+}
+
+.audiocontrols {
+ bottom: 0;
+ left: 0;
+ z-index:999;
+ height: 30px;
+ right: 0;
+ position:absolute;
+ background: -webkit-gradient(linear,
+ left top,
+ left bottom,
+ from(#323232),
+ to(#070707));
+}
+
+.audio.playbutton {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ cursor: pointer;
+ z-index: 9999;
+ width: 30px;
+ background: url('../../app/theme/mediaplayer_play.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+ height: 30px;
+}
+
+.audio.soundbutton {
+ position:absolute;
+ cursor: pointer;
+ right: 30px;
+ bottom:0;
+ z-index: 9999;
+ width: 30px;
+ background: url('../../app/theme/mediaplayer_vol_high.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+ height: 30px;
+}
+
+.video.soundbutton {
+ position:absolute;
+ right: 30px;
+ cursor: pointer;
+ bottom:0;
+ z-index: 9999;
+ width: 30px;
+ background: url('../../app/theme/mediaplayer_vol_high.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+ height: 30px;
+}
+
+.audio.volume {
+ position: absolute;
+ bottom: 30px;
+ height: 80px;
+ width: 30px;
+ right: 30px;
+ background: black;
+ background: -webkit-gradient(linear,
+ left top,
+ left bottom,
+ from(#323232),
+ to(#070707));
+}
+
+.video.volume {
+ position: absolute;
+ bottom: 30px;
+ height: 80px;
+ width: 30px;
+ right: 30px;
+ background: black;
+ background: -webkit-gradient(linear,
+ left top,
+ left bottom,
+ from(#323232),
+ to(#070707));
+}
+
+.volumeslider {
+ -webkit-appearance: slider-vertical;
+ position: absolute;
+ left: 0;
+ right:0;
+ bottom:0;
+ top: 0;
+}
+
+.video.playbutton {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ cursor: pointer;
+ z-index: 9999;
+ width: 30px;
+ background: url('../../app/theme/mediaplayer_play.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+ height: 30px;
+}
+
+.audio.pausebutton {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ cursor: pointer;
+ z-index: 9999;
+ width: 30px;
+ height: 30px;
+ background: url('../../app/theme/mediaplayer_pause.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.video.pausebutton {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ cursor: pointer;
+ z-index: 9999;
+ width: 30px;
+ height: 30px;
+ background: url('../../app/theme/mediaplayer_pause.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.video.prevbutton {
+ position: absolute;
+ left:30px;
+ cursor:pointer;
+ bottom:0;
+ width:30px;
+ height:30px;
+ background: url('../../app/theme/mediaplayer_prev.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.playbackvideoelement {
+ width:100%;
+ height:100%;
+ position: absolute;
+ left:0;
+ top:0;
+}
+
+.duration {
+ right: 58px;
+ color: white;
+ position: absolute;
+ top: 7px;
+ font-size: .6em;
+}
+
+.playbackaudioelement {
+ width:100%;
+ height:100%;
+ position: absolute;
+ left:0;
+ top:0;
+}
+
+.audio.prevbutton {
+ position: absolute;
+ left:30px;
+ cursor:pointer;
+ bottom:0;
+ width:30px;
+ height:30px;
+ background: url('../../app/theme/mediaplayer_prev.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.video.nextbutton {
+ position: absolute;
+ left:60px;
+ cursor:pointer;
+ bottom:0;
+ z-index: 9999;
+ width:30px;
+ height:30px;
+ background: url('../../app/theme/mediaplayer_next.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.playlistbutton {
+ position: absolute;
+ right: 0;
+ cursor:pointer;
+ z-index: 9999;
+ bottom: 0;
+ width: 30px;
+ height: 30px;
+ background: url('../../app/theme/mediaplayer_menu.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+.audio.nextbutton {
+ position: absolute;
+ left:60px;
+ cursor:pointer;
+ bottom:0;
+ z-index: 9999;
+ width:30px;
+ height:30px;
+ background: url('../../app/theme/mediaplayer_next.png');
+ background-repeat: no-repeat;
+ background-position: 8px 8px;
+}
+
+</style>
+<script src='local_strings.js'></script>
+<script>
+
+function $(o) {
+ return document.getElementById(o);
+}
+
+function pathIsVideoFile(path) {
+ return /\.(mp4|ogg|mpg|avi)$/i.test(path);
+};
+
+function pathIsAudioFile(path) {
+ return /\.(mp3|m4a)$/i.test(path);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Document Functions:
+/**
+ * Window onload handler, sets up the page.
+ */
+function load() {
+ chrome.send('getCurrentPlaylist', []);
+};
+
+var videoPlaybackElement = null;
+var audioPlaybackElement = null;
+var currentPlaylist = null;
+var currentItem = -1;
+
+function onMediaProgress() {
+ var element = getMediaElement();
+ var current = element.currentTime;
+ var duration = element.duration;
+ var progress = $('progress');
+ progress.value = (current*100)/duration;
+ if (progress.value == 100) {
+ onMediaComplete();
+ }
+};
+
+function onMediaError(e) {
+ chrome.send('playbackError', ['Error playing back']);
+ onMediaComplete();
+};
+
+function onMediaComplete() {
+ var mediaElement = getMediaElement();
+ mediaElement.removeEventListener("timeupdate", onMediaProgress, true);
+ mediaElement.removeEventListener("durationchange", onMetadataAvail, true);
+ // MediaElement.removeEventListener("ended", onMediaComplete, true);
+ mediaElement.removeEventListener("play", onMediaPlay, true);
+ mediaElement.removeEventListener("pause", onMediaPause, true);
+ currentItem ++;
+
+ if (currentItem >= currentPlaylist.length) {
+ currentItem = -1;
+ return;
+ }
+ chrome.send('currentOffsetChanged', ['' + currentItem]);
+ playMediaFile(currentPlaylist[currentItem].path);
+};
+
+function onMediaPlay() {
+ var pausebutton = $('pausebutton');
+ var playbutton = $('playbutton');
+ pausebutton.style.display = 'block';
+ playbutton.style.display = 'none';
+};
+
+function onMediaPause() {
+ var pausebutton = $('pausebutton');
+ var playbutton = $('playbutton');
+ playbutton.style.display = 'block';
+ pausebutton.style.display = 'none';
+};
+
+function setupMediaEvents(element) {
+ element.addEventListener("timeupdate", onMediaProgress, true);
+ element.addEventListener("durationchange", onMetadataAvail, true);
+ // element.addEventListener("ended", onMediaComplete, true);
+ element.onerror = onMediaError;
+ element.addEventListener("play", onMediaPlay, true);
+ element.addEventListener("pause", onMediaPause, true);
+};
+
+function getMediaElement() {
+ var mediaElement;
+ if (videoPlaybackElement) {
+ mediaElement = videoPlaybackElement;
+ } else {
+ mediaElement = audioPlaybackElement;
+ }
+ return mediaElement;
+};
+
+function playPauseButtonClick() {
+ var mediaElement = getMediaElement();
+ if (mediaElement.paused || mediaElement.ended) {
+ mediaElement.play();
+ } else {
+ mediaElement.pause();
+ }
+};
+
+function prevButtonClick() {
+ var element = getMediaElement();
+ if (element.currentTime > 6) {
+ element.currentTime = 0;
+ return;
+ }
+ currentItem --;
+ if (currentItem < 0) {
+ currentItem = -1;
+ return;
+ }
+ chrome.send('currentOffsetChanged', ['' + currentItem]);
+ playMediaFile(currentPlaylist[currentItem].path);
+};
+
+function nextButtonClick() {
+ currentItem ++;
+ if (currentItem >= currentPlaylist.length) {
+ currentItem = -1;
+ return;
+ }
+ chrome.send('currentOffsetChanged', ['' + currentItem]);
+ playMediaFile(currentPlaylist[currentItem].path);
+};
+
+function userChangedProgress() {
+ var val = $('progress').value;
+ var element = getMediaElement();
+ if (element.seekable && element.duration) {
+ var current = (progress.value * element.duration)/100;
+ element.currentTime = current;
+ }
+};
+
+function toggleVolumeVisible() {
+ var volume_div = $('volume');
+ if (volume_div.style.display == 'none') {
+ volume_div.style.display = 'block';
+ } else {
+ volume_div.style.display = 'none';
+ }
+};
+
+function volumeChange() {
+ var volumeslider = $('volumeslider');
+ var element = getMediaElement();
+ element.volume = (volumeslider.value/100);
+};
+
+function setupPlaybackControls() {
+ var element = $('playercontrols');
+ playercontrols.innerHTML = ''; // clear out other
+ var controlsclass = '';
+ if (videoPlaybackElement != null) {
+ controlsclass = 'video';
+ element.className = 'videocontrols';
+ } else if (audioPlaybackElement != null) {
+ controlsclass = 'audio';
+ element.className = 'audiocontrols';
+ }
+
+ var playbutton = document.createElement('div');
+ playbutton.id = 'playbutton';
+ playbutton.className = controlsclass + ' playbutton';
+ playbutton.onclick = playPauseButtonClick;
+ element.appendChild(playbutton);
+
+
+ var pausebutton = document.createElement('div');
+ pausebutton.id = 'pausebutton';
+ pausebutton.className = controlsclass + ' pausebutton';
+ pausebutton.onclick = playPauseButtonClick;
+ element.appendChild(pausebutton);
+
+ var nextbutton = document.createElement('div');
+ nextbutton.id = 'nextbutton';
+ nextbutton.className = controlsclass + ' nextbutton';
+ nextbutton.onclick = nextButtonClick;
+ element.appendChild(nextbutton);
+
+ var prevbutton = document.createElement('div');
+ prevbutton.id = 'prevbutton';
+ prevbutton.className = controlsclass + ' prevbutton';
+ prevbutton.onclick = prevButtonClick;
+ element.appendChild(prevbutton);
+
+ var playlistbutton = document.createElement('div');
+ playlistbutton.id = 'playlistbutton';
+ playlistbutton.className = 'playlistbutton';
+ playlistbutton.onclick = togglePlaylist;
+ element.appendChild(playlistbutton);
+
+ var slider = document.createElement('input');
+ slider.type = 'range';
+ slider.id = 'progress';
+ slider.className = controlsclass + ' progress';
+ slider.onchange = userChangedProgress;
+ element.appendChild(slider);
+
+ var soundbutton = document.createElement('div');
+ soundbutton.id = 'soundbutton';
+ soundbutton.className = controlsclass + ' soundbutton';
+ soundbutton.onclick = toggleVolumeVisible;
+ element.appendChild(soundbutton);
+
+ var volume = document.createElement('div');
+ volume.id = 'volume';
+ volume.className = controlsclass + ' volume';
+ volume.style.display = 'none';
+ var volumeslider = document.createElement('input');
+ volumeslider.type = 'range';
+ volumeslider.id = 'volumeslider';
+ volumeslider.className = 'volumeslider';
+ volumeslider.onchange = volumeChange;
+ volume.appendChild(volumeslider);
+ document.body.appendChild(volume);
+
+ var duration = document.createElement('div');
+ duration.id = 'duration';
+ duration.className = 'duration';
+ element.appendChild(duration);
+};
+
+function playAudioFile(uri) {
+ if (videoPlaybackElement != null) {
+ document.body.removeChild(videoPlaybackElement);
+ videoPlaybackElement = null;
+ }
+ if (audioPlaybackElement == null) {
+ audioPlaybackElement = document.createElement('audio');
+ audioPlaybackElement.className = 'playbackaudioelement';
+ audioPlaybackElement.autoplay = true;
+ audioPlaybackElement.controls = false;
+ setupMediaEvents(audioPlaybackElement);
+ audioPlaybackElement.src = uri;
+ setupPlaybackControls();
+ document.body.appendChild(audioPlaybackElement);
+ } else {
+ setupMediaEvents(audioPlaybackElement);
+ audioPlaybackElement.src = uri;
+ audioPlaybackElement.currentTime = 0;
+ audioPlaybackElement.load();
+ audioPlaybackElement.play();
+ }
+};
+
+function toggleFullscreen() {
+
+};
+
+function onMetadataAvail() {
+ var element = getMediaElement();
+ var duration = element.duration;
+ if (duration) {
+ var durString = '' + Math.floor((duration / 60)) + ':' + (Math.floor(duration) % 60);
+ var durDiv = $('duration');
+ durDiv.textContent = durString;
+ }
+};
+
+function playVideoFile(uri) {
+ if (audioPlaybackElement != null) {
+ document.body.removeChild(audioPlaybackElement);
+ audioPlaybackElement = null;
+ }
+ if (videoPlaybackElement == null) {
+ videoPlaybackElement = document.createElement('video');
+ videoPlaybackElement.className = 'playbackvideoelement';
+ videoPlaybackElement.autoplay = true;
+ videoPlaybackElement.controls = false;
+ setupMediaEvents(videoPlaybackElement);
+ videoPlaybackElement.src = uri;
+ videoPlaybackElement.load();
+ var toggleButton = document.createElement('div');
+ toggleButton.className = 'fullscreentoggle';
+ toggleButton.id = 'fullscreentoggle';
+ toggleButton.onclick = toggleFullscreen;
+ document.body.appendChild(toggleButton);
+ setupPlaybackControls();
+ document.body.appendChild(videoPlaybackElement);
+ } else {
+ setupMediaEvents(videoPlaybackElement);
+ videoPlaybackElement.src = uri;
+ videoPlaybackElement.currentTime = 0;
+ videoPlaybackElement.load();
+ videoPlaybackElement.play();
+ }
+};
+
+function stopAllPlayback() {
+ var element = getMediaElement();
+ if (element != null) {
+ element.pause();
+ }
+};
+
+function playlistChanged(info, playlist) {
+ if (info.force) {
+ currentPlaylist = playlist;
+ stopAllPlayback();
+ if (playlist.length >= 1) {
+ if (info.currentOffset) {
+ currentItem = info.currentOffset;
+ } else {
+ currentItem = 0;
+ }
+ var item = playlist[currentItem];
+ playMediaFile(item.path);
+ }
+ } else {
+ var media = getMediaElement();
+ currentPlaylist = playlist;
+ // Only need to handle the case where we are not playing
+ // since if it is currently playing, it will just move
+ // to the next file when the current is complete.
+ if (media == null || media.ended == true) {
+ for (var x = 0; x < playlist.length; x++) {
+ if (playlist[x].path == info.path) {
+ // found the newly added item.
+ currentItem = x;
+ chrome.send('currentOffsetChanged', ['' + currentItem]);
+ playMediaFile(playlist[x].path);
+ return;
+ }
+ }
+ if (playlist.length > 0) {
+ currentItem = 0;
+ chrome.send('currentOffsetChanged', ['' + currentItem]);
+ playMediaFile(playlist[0].path);
+ }
+ }
+ }
+};
+
+function togglePlaylist() {
+ chrome.send("togglePlaylist", []);
+};
+
+function playMediaFile(url) {
+ if (pathIsVideoFile(url) ) {
+ playVideoFile(url);
+ } else if(pathIsAudioFile(url)) {
+ playAudioFile(url);
+ } else {
+ alert('file unknown');
+ }
+};
+
+</script>
+<body onload='load();' onselectstart='return false'>
+<div id='playercontrols' class='playercontrols'>
+</div>
+</body>
+</html>
diff --git a/chrome/browser/resources/playlist.html b/chrome/browser/resources/playlist.html
new file mode 100644
index 0000000..80415f6
--- /dev/null
+++ b/chrome/browser/resources/playlist.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<meta charset="utf-8">
+<title>Media Playlist</title>
+<style type="text/css">
+
+.playlist {
+ width: 100%;
+ height: 100%;
+ background: #080809;
+ color: #8AACE7;
+ font-size: .7em;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.playlistitem {
+ width: 100%;
+ padding: 6px;
+ cursor: pointer;
+}
+
+.playing {
+ background: #393b41;
+ color: #dddde7;
+ font-weight: bold;
+}
+
+.tracknum {
+ width: 20px;
+ position: relative;
+ float: left;
+}
+
+.title {
+
+}
+
+</style>
+<script src='local_strings.js'></script>
+<script>
+
+function $(o) {
+ return document.getElementById(o);
+}
+
+function pathIsVideoFile(path) {
+ return /\.(mp4|ogg|mpg|avi)$/i.test(path);
+};
+
+function pathIsAudioFile(path) {
+ return /\.(mp3|m4a)$/i.test(path);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Document Functions:
+/**
+ * Window onload handler, sets up the page.
+ */
+
+var currentPlaylist = null;
+var currentOffset = -1;
+function load() {
+ chrome.send("getCurrentPlaylist", []);
+};
+
+function getDisplayNameFromPath(path) {
+ slash = path.lastIndexOf("/")
+ if (slash != -1) {
+ fileName = path.substring(slash+1,path.length)
+ return fileName;
+ } else {
+ return path;
+ }
+};
+
+function setPlaylistOffset(offset) {
+ chrome.send("setCurrentPlaylistOffset", ['' + offset]);
+};
+
+function updateUI() {
+ var main = $('main');
+ if (currentPlaylist) {
+ main.innerHTML = '';
+ var main = $('main');
+ for (var x = 0; x < currentPlaylist.length; x++) {
+ var rowdiv = document.createElement('div');
+ rowdiv.className = 'playlistitem';
+
+ var numberdiv = document.createElement('div');
+ numberdiv.className = 'tracknum';
+ numberdiv.textContent = '' + (x + 1);
+ rowdiv.appendChild(numberdiv);
+
+ var titlediv = document.createElement('div');
+ titlediv.classname = 'title';
+ titlediv.textContent = getDisplayNameFromPath(currentPlaylist[x].path);
+ rowdiv.appendChild(titlediv);
+ rowdiv.onclick = new Function('setPlaylistOffset(' + x + ')');
+ if (currentOffset == x) {
+ rowdiv.className = 'playlistitem playing';
+ }
+ main.appendChild(rowdiv);
+ }
+ }
+};
+
+function playlistChanged(info, playlist) {
+ currentPlaylist = playlist;
+ currentOffset = info.currentOffset;
+ updateUI();
+};
+</script>
+<body onload='load();' onselectstart='return false'>
+<div id='main' class='playlist'>
+</div>
+</body>
+</html>
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index fb75ba1..026eebb 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -818,6 +818,8 @@
'browser/dom_ui/html_dialog_tab_contents_delegate.h',
'browser/dom_ui/html_dialog_ui.cc',
'browser/dom_ui/html_dialog_ui.h',
+ 'browser/dom_ui/mediaplayer_ui.cc',
+ 'browser/dom_ui/mediaplayer_ui.h',
'browser/dom_ui/most_visited_handler.cc',
'browser/dom_ui/most_visited_handler.h',
'browser/dom_ui/new_tab_page_sync_handler.cc',
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index f2e3ff7..156ca96 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -56,6 +56,7 @@ const char kChromeUIDownloadsURL[] = "chrome://downloads/";
const char kChromeUIExtensionsURL[] = "chrome://extensions/";
const char kChromeUIHistoryURL[] = "chrome://history/";
const char kChromeUIFileBrowseURL[] = "chrome://filebrowse/";
+const char kChromeUIMediaplayerURL[] = "chrome://mediaplayer/";
const char kChromeUIIPCURL[] = "chrome://about/ipc";
const char kChromeUINetworkURL[] = "chrome://about/network";
const char kChromeUINewTabURL[] = "chrome://newtab";
@@ -68,6 +69,7 @@ const char kChromeUIExtensionsHost[] = "extensions";
const char kChromeUIFavIconPath[] = "favicon";
const char kChromeUIHistoryHost[] = "history";
const char kChromeUIFileBrowseHost[] = "filebrowse";
+const char kChromeUIMediaplayerHost[] = "mediaplayer";
const char kChromeUIInspectorHost[] = "inspector";
const char kChromeUINewTabHost[] = "newtab";
const char kChromeUIThumbnailPath[] = "thumb";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index a44992f..ac03c81 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -52,6 +52,7 @@ extern const char kChromeUIDownloadsURL[];
extern const char kChromeUIExtensionsURL[];
extern const char kChromeUIHistoryURL[];
extern const char kChromeUIFileBrowseURL[];
+extern const char kChromeUIMediaplayerURL[];
extern const char kChromeUIIPCURL[];
extern const char kChromeUINetworkURL[];
extern const char kChromeUINewTabURL[];
@@ -66,6 +67,7 @@ extern const char kChromeUIExtensionsHost[];
extern const char kChromeUIFavIconPath[];
extern const char kChromeUIHistoryHost[];
extern const char kChromeUIFileBrowseHost[];
+extern const char kChromeUIMediaplayerHost[];
extern const char kChromeUIInspectorHost[];
extern const char kChromeUINewTabHost[];
extern const char kChromeUIThumbnailPath[];