onGenericMessage_(event) {
    const message = shaka.cast.CastUtils.deserialize(event.data);
    shaka.log.debug('CastReceiver: message', message);
    // TODO(ismena): error message on duplicate request id from the same sender
    switch (message['type']) {
      case 'PLAY':
        this.video_.play();
        // Notify generic controllers that the player state changed.
        // requestId=0 (the parameter) means that the message was not
        // triggered by a GET_STATUS request.
        this.sendMediaStatus_();
        break;
      case 'PAUSE':
        this.video_.pause();
        this.sendMediaStatus_();
        break;
      case 'SEEK': {
        const currentTime = message['currentTime'];
        const resumeState = message['resumeState'];
        if (currentTime != null) {
          this.video_.currentTime = Number(currentTime);
        }
        if (resumeState && resumeState == 'PLAYBACK_START') {
          this.video_.play();
          this.sendMediaStatus_();
        } else if (resumeState && resumeState == 'PLAYBACK_PAUSE') {
          this.video_.pause();
          this.sendMediaStatus_();
        }
        break;
      }
      case 'STOP':
        this.player_.unload().then(() => {
          if (!this.player_) {
            // We've already been destroyed.
            return;
          }

          this.sendMediaStatus_();
        });
        break;
      case 'GET_STATUS':
        // TODO(ismena): According to the SDK this is supposed to be a
        // unicast message to the sender that requested the status,
        // but it doesn't appear to be working.
        // Look into what's going on there and change this to be a
        // unicast.
        this.sendMediaInfoMessage_(Number(message['requestId']));
        break;
      case 'VOLUME': {
        const volumeObject = message['volume'];
        const level = volumeObject['level'];
        const muted = volumeObject['muted'];
        const oldVolumeLevel = this.video_.volume;
        const oldVolumeMuted = this.video_.muted;
        if (level != null) {
          this.video_.volume = Number(level);
        }
        if (muted != null) {
          this.video_.muted = muted;
        }
        // Notify generic controllers if the volume changed.
        if (oldVolumeLevel != this.video_.volume ||
            oldVolumeMuted != this.video_.muted) {
          this.sendMediaStatus_();
        }
        break;
      }
      case 'LOAD': {
        // Reset update message frequency values after a load.
        this.updateNumber_ = 0;
        this.startUpdatingUpdateNumber_ = false;
        // This already sends an update.
        this.initialStatusUpdatePending_ = false;

        const mediaInfo = message['media'];
        const contentId = mediaInfo['contentId'];
        const currentTime = message['currentTime'];
        const assetUri = this.contentIdCallback_(contentId);
        const autoplay = message['autoplay'] || true;
        const customData = mediaInfo['customData'];

        this.appDataCallback_(customData);

        if (autoplay) {
          this.video_.autoplay = true;
        }
        this.player_.load(assetUri, currentTime).then(() => {
          if (!this.player_) {
            // We've already been destroyed.
            return;
          }

          // Notify generic controllers that the media has changed.
          this.sendMediaInfoMessage_();
        }).catch((error) => {
          goog.asserts.assert(error instanceof shaka.util.Error,
              'Wrong error type!');

          // Load failed.  Dispatch the error message to the sender.
          let type = 'LOAD_FAILED';
          if (error.category == shaka.util.Error.Category.PLAYER &&
              error.code == shaka.util.Error.Code.LOAD_INTERRUPTED) {
            type = 'LOAD_CANCELLED';
          }

          this.sendMessage_({
            'requestId': Number(message['requestId']),
            'type': type,
          }, this.genericBus_);
        });
        break;
      }
      default:
        shaka.log.warning(
            'Unrecognized message type from the generic Chromecast controller!',
            message['type']);
        // Dispatch an error to the sender.
        this.sendMessage_({
          'requestId': Number(message['requestId']),
          'type': 'INVALID_REQUEST',
          'reason': 'INVALID_COMMAND',
        }, this.genericBus_);
        break;
    }
  }
@param {!cast.receiver.CastMessageBus.Event} event
@private