# Media Browse

Cast Media Browse (CMB) is a feature that lets smart display users
discover and engage with your audio or video content catalog. CMB does so by
enhancing the Web Receiver with a streamlined browsing experience that is
specially tuned for smart displays.

CMB defines standardized templates that deliver a consistent browsing experience
that follows smart display UI conventions. Developers supply data to populate
these standardized templates. Templates support both audio and video content or
a mix of both.

## Entry points

There are two entry points for CMB, from which a user can browse and select
content using touch or voice control.

### In-player browse

Swipe up during playback to choose from a list of application-supplied content:

*Video*

![Media Browse Entry - In Player Video 1](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-in-player-video01.png) ![Media Browse Entry - In Player Video 2](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-in-player-video02.png)

*Audio*

![Media Browse Entry - In Player Audio 1](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-in-player-audio01.png) ![Media Browse Entry - In Player Audio 2](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-in-player-audio02.png)

### Landing page browse

When a Web Receiver with the `cast-media-player` element is running on Smart
Displays, it shows CMB while in the IDLE state.

*Video and Audio*

![Media Browse Entry - Landing Page Video](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-landing-page-video.png) ![Media Browse Entry - Landing Page Audio](https://developers.google.com/static/cast/images/media-browse/cast-mb-entry-landing-page-audio.png)

## Populating content

Developers are responsible for populating the template for each entry point with
data for each content item. The content used to populate In-Player Browse can be
different than the content used to populate Landing Page Browse.

Use In-Player Browse to display items that relate to the content a user is
currently playing, or items of a playlist. Live TV providers could also use this
entry point to populate a list of channels for easy access.

Use Landing Page Browse to raise awareness of new original content, content that
is currently live, or content that might be of further interest to your user.

> [!WARNING]
> **Warning:** To prevent performance issues, the maximum Media Browse item count is 30 items.

## Enable Media Browse

Provide a list of media contents for browsing by calling [`setBrowseContent`](https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.ui.Controls#setBrowseContent):

```
const controls = cast.framework.ui.Controls.getInstance();
controls.setBrowseContent(BrowseContent);
```

The Media Browse UI is updated immediately after calling this method.

### Safe area height

When CMB is enabled, the height of the Cast SDK UI safe area changes, and you
might need to update your existing Web Receiver UI. Use
[`getSafeAreaHeight`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.Controls#getSafeAreaHeight)
to determine the height of the safe area.

```
// Media Browse UI enabled
controls.setBrowseContent(BrowseContent);
console.log(controls.getSafeAreaHeight()); // 338px on Google Nest Hub

// Media Browse UI disabled
controls.setBrowseContent(null);
console.log(controls.getSafeAreaHeight()); // 408px on Google Nest Hub
```

## Remove Media Browse

To remove the Media Browse UI, use `null` with `setBrowseContent`:

```
controls.setBrowseContent(null);
```

## Customize Media Browse

### Browsing content

Use
[`BrowseContent`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseContent)
to customize the title of the Media Browse UI and update items:

![Media Browse - Browse Content](https://developers.google.com/static/cast/images/media-browse/cast-mb-browse-content.png)
> A. [`BrowseContent.title`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseContent#title)
>
> B. [`BrowseContent.items`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseContent#items)

Use
[`BrowseItem`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseItem)
to display title, subtitle, duration, and image for each item in the Media
Browse UI:

![Media Browse - Browse Item](https://developers.google.com/static/cast/images/media-browse/cast-mb-browse-item.png)
> A. [`BrowseItem.image`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseItem#image)
>
> B. [`BrowseItem.duration`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseItem#duration)
>
> C. [`BrowseItem.title`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseItem#title)
>
> D. [`BrowseItem.subtitle`](https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.ui.BrowseItem#subtitle)

### Aspect ratio

Use [`targetAspectRatio`](https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.ui.BrowseContent#targetAspectRatio)
to select the best aspect ratio for your image assets. Three aspect ratios are
supported by the Web Receiver SDK:

| Aspect Ratio | Example |
|---|---|
| `SQUARE_1_TO_1` | ![Media Browse - Square Aspect Ratio](https://developers.google.com/static/cast/images/media-browse/cast-mb-aspectratio-square.png) |
| `PORTRAIT_2_TO_3` | ![Media Browse - Portrait Aspect Ratio](https://developers.google.com/static/cast/images/media-browse/cast-mb-aspectratio-portrait.png) |
| `LANDSCAPE_16_TO_9` | ![Media Browse - Landscape Aspect Ratio](https://developers.google.com/static/cast/images/media-browse/cast-mb-aspectratio-landscape.png) |

### Messages

When a user selects one of the items from the Media Browse UI, the Web Receiver
SDK sends a `LOAD` message to the application according to
the values of the selected `BrowseItem`.

## Sample code

    const controls = cast.framework.ui.Controls.getInstance();

    const item1 = new cast.framework.ui.BrowseItem();
    item1.title = 'Title 1';
    item1.subtitle = 'Subtitle 1';
    item1.duration = 300;
    item1.imageType = cast.framework.ui.BrowseImageType.MUSIC_TRACK;
    item1.image = new cast.framework.messages.Image('1.jpg');
    item1.entity = 'example://gizmos/1';

    const item2 = new cast.framework.ui.BrowseItem();
    item2.title = 'Title 2';
    item2.subtitle = 'Subtitle 2';
    item2.duration = 100;
    item2.imageType = cast.framework.ui.BrowseImageType.MUSIC_TRACK;
    item2.image = new cast.framework.messages.Image('2.jpg');
    item2.entity = 'example://gizmos/2';

    const items = [item1, item2];

    const browseContent = new cast.framework.ui.BrowseContent();
    browseContent.title = 'Up Next';
    browseContent.items = items;

    playerDataBinder.addEventListener(
      cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
      (e) => {
        // Media browse
        controls.setBrowseContent(browseContent);
      });

    playerManager.setMessageInterceptor(
      cast.framework.messages.MessageType.LOAD, loadRequestData => {
        if (loadRequestData.media && loadRequestData.media.entity) {
          // Load by entity
          loadRequestData.media.contentId = entityToId(loadRequestData.media.entity);
          loadRequestData.media.contentUrl = entityToUrl(loadRequestData.media.entity);
        }
        return loadRequestData;
      });