Commit 26ae1fd0 authored by Takumi Fujimoto's avatar Takumi Fujimoto Committed by Commit Bot

GMC+Cast: Show artist names and rearrange labels

This CL adds a secondary_title field to media_router.mojom.MediaStatus,
corresponding to the media.metadata.subtitle field in Cast SDK media
status messages, which contains artist names for media.

The artist name is shown in a Cast notification item in Global Media
Controls. Other labels are also rearranged to match the mocks.

Screenshot:
https://drive.google.com/file/d/1Ecr-7WsGFE7Be3MuPvsau3SEUwKPQPJr/view?usp=sharing

Bug: 1042016
Change-Id: Iff3cc50af41ef24e6a4e8ec10090acbffe049f8f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2003388
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarmark a. foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732551}
parent 2e6955cc
......@@ -189,6 +189,8 @@ void CastMediaController::UpdateMediaStatus(const base::Value& message_value) {
SetIfValid(&media_session_id_, status_value.FindKey("mediaSessionId"));
SetIfValid(&media_status_.title,
status_value.FindPath("media.metadata.title"));
SetIfValid(&media_status_.secondary_title,
status_value.FindPath("media.metadata.subtitle"));
SetIfValid(&media_status_.current_time, status_value.FindKey("currentTime"));
SetIfValid(&media_status_.duration, status_value.FindPath("media.duration"));
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h"
#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/global_media_controls/cast_media_session_controller.h"
......@@ -111,6 +112,21 @@ media_session::mojom::MediaSessionInfo::SessionState ToSessionState(
}
}
base::string16 GetSourceTitle(const media_router::MediaRoute& route) {
if (route.media_sink_name().empty())
return base::UTF8ToUTF16(route.description());
if (route.description().empty())
return base::UTF8ToUTF16(route.media_sink_name());
const char kSeparator[] = " \xC2\xB7 "; // "Middle dot" character.
const std::string source_title =
base::i18n::IsRTL()
? route.media_sink_name() + kSeparator + route.description()
: route.description() + kSeparator + route.media_sink_name();
return base::UTF8ToUTF16(source_title);
}
} // namespace
CastMediaNotificationItem::CastMediaNotificationItem(
......@@ -126,8 +142,7 @@ CastMediaNotificationItem::CastMediaNotificationItem(
base::BindRepeating(&CastMediaNotificationItem::ImageChanged,
base::Unretained(this))),
session_info_(CreateSessionInfo()) {
metadata_.source_title = base::UTF8ToUTF16(route.media_sink_name());
metadata_.artist = base::UTF8ToUTF16(route.description());
metadata_.source_title = GetSourceTitle(route);
notification_controller_->ShowNotification(media_route_id_);
}
......@@ -153,6 +168,7 @@ void CastMediaNotificationItem::Dismiss() {
void CastMediaNotificationItem::OnMediaStatusUpdated(
media_router::mojom::MediaStatusPtr status) {
metadata_.title = base::UTF8ToUTF16(status->title);
metadata_.artist = base::UTF8ToUTF16(status->secondary_title);
actions_ = ToMediaSessionActions(*status);
session_info_->state = ToSessionState(status->play_state);
session_info_->playback_state = ToPlaybackState(status->play_state);
......@@ -171,8 +187,7 @@ void CastMediaNotificationItem::OnRouteUpdated(
const media_router::MediaRoute& route) {
DCHECK_EQ(route.media_route_id(), media_route_id_);
bool updated = false;
const base::string16 new_source_title =
base::UTF8ToUTF16(route.media_sink_name());
const base::string16 new_source_title = GetSourceTitle(route);
if (metadata_.source_title != new_source_title) {
metadata_.source_title = new_source_title;
updated = true;
......
......@@ -24,7 +24,7 @@ using testing::AtLeast;
namespace {
constexpr char kRouteDesc[] = "route description";
constexpr char kRouteDesc[] = "My App";
constexpr char kRouteId[] = "route_id";
constexpr char kSinkName[] = "My Sink";
......@@ -119,8 +119,9 @@ class CastMediaNotificationItemTest : public testing::Test {
});
EXPECT_CALL(view_, UpdateWithMediaMetadata(_))
.WillOnce([&](const media_session::MediaMetadata& metadata) {
EXPECT_EQ(base::UTF8ToUTF16(kRouteDesc), metadata.artist);
EXPECT_EQ(base::UTF8ToUTF16(kSinkName), metadata.source_title);
const std::string separator = " \xC2\xB7 ";
EXPECT_EQ(base::UTF8ToUTF16(kRouteDesc + separator + kSinkName),
metadata.source_title);
});
item_->SetView(&view_);
testing::Mock::VerifyAndClearExpectations(&view_);
......@@ -167,11 +168,14 @@ TEST_F(CastMediaNotificationItemTest, UpdateSessionInfo) {
TEST_F(CastMediaNotificationItemTest, UpdateMetadata) {
SetView();
auto status = MediaStatus::New();
std::string title = "my title";
const std::string title = "my title";
const std::string secondary_title = "my artist";
status->title = title;
status->secondary_title = secondary_title;
EXPECT_CALL(view_, UpdateWithMediaMetadata(_))
.WillOnce([&](const media_session::MediaMetadata& metadata) {
EXPECT_EQ(base::UTF8ToUTF16(title), metadata.title);
EXPECT_EQ(base::UTF8ToUTF16(secondary_title), metadata.artist);
});
item_->OnMediaStatusUpdated(std::move(status));
}
......
......@@ -117,8 +117,9 @@ TEST_F(CastMediaNotificationProviderTest, UpdateRoute) {
EXPECT_CALL(view, UpdateWithMediaMetadata(_))
.WillOnce([&](const media_session::MediaMetadata& metadata) {
EXPECT_EQ(base::UTF8ToUTF16(new_sink), metadata.source_title);
EXPECT_EQ(base::UTF8ToUTF16(new_description), metadata.artist);
const std::string separator = " \xC2\xB7 ";
EXPECT_EQ(base::UTF8ToUTF16(new_description + separator + new_sink),
metadata.source_title);
});
notification_provider_->OnRoutesUpdated({route}, {});
}
......@@ -31,6 +31,11 @@ struct MediaStatus {
// For a Presentation API route, it is the presentation page title.
string title;
// The secondary label for the currently playing media. For example, this may
// be the artist name for a video or a song. It may be empty for mirroring or
// non-Cast-SDK Presentation API routes.
string secondary_title;
// If this is true, the media can be played and paused through its
// MediaController.
bool can_play_pause;
......
......@@ -149,6 +149,7 @@ IPEndpointAdapter.prototype.toNewVersion = function() {
*/
function MediaStatusAdapter(fields) {
this.title = null;
this.secondary_title = null;
this.can_play_pause = false;
this.can_mute = false;
this.can_set_volume = false;
......@@ -170,6 +171,7 @@ MediaStatusAdapter.PlayState = mediaRouter.mojom.MediaStatus.PlayState;
MediaStatusAdapter.prototype.toNewVersion = function() {
return new mediaRouter.mojom.MediaStatus({
'title': this.title,
'secondaryTitle': this.secondary_title || '',
'canPlayPause': this.can_play_pause,
'canMute': this.can_mute,
'canSetVolume': this.can_set_volume,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment