Esempio n. 1
0
 public void setAudioDelay(long value) {
   if (!nativeMode && mVlcPlayer != null) {
     if (!mVlcPlayer.setAudioDelay(value * 1000)) {
       TvApp.getApplication().getLogger().Error("Error setting audio delay");
     } else {
       TvApp.getApplication().getLogger().Info("Audio delay set to " + value);
     }
   }
 }
Esempio n. 2
0
  public String getSubText() {
    switch (type) {
      case BaseItem:
        return Utils.GetSubName(baseItem);
      case Person:
        return person.getRole();
      case Chapter:
        Long pos = chapterInfo.getStartPositionTicks() / 10000;
        return Utils.formatMillis(pos.intValue());
      case Server:
        return serverInfo.getLocalAddress().substring(7);
      case LiveTvChannel:
        return channelInfo.getNumber();
      case LiveTvProgram:
        Calendar start = Calendar.getInstance();
        start.setTime(Utils.convertToLocalDate(baseItem.getStartDate()));
        int day = start.get(Calendar.DAY_OF_YEAR);
        return baseItem.getChannelName()
            + " - "
            + (baseItem.getEpisodeTitle() != null ? baseItem.getEpisodeTitle() : "")
            + " "
            + ((day != Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
                    ? new SimpleDateFormat("d MMM").format(start.getTime()) + " "
                    : "")
                + android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                    .format(start.getTime())
                + "-"
                + android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                    .format(Utils.convertToLocalDate(baseItem.getEndDate())));
      case LiveTvRecording:
        return (baseItem.getChannelName() != null ? baseItem.getChannelName() + " - " : "")
            + (baseItem.getEpisodeTitle() != null ? baseItem.getEpisodeTitle() : "")
            + " "
            + new SimpleDateFormat("d MMM")
                .format(Utils.convertToLocalDate(baseItem.getStartDate()))
            + " "
            + (android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                    .format(Utils.convertToLocalDate(baseItem.getStartDate()))
                + "-"
                + android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                    .format(Utils.convertToLocalDate(baseItem.getEndDate())));
      case User:
        Date date = user.getLastActivityDate();
        return date != null
            ? DateUtils.getRelativeTimeSpanString(Utils.convertToLocalDate(date).getTime())
                .toString()
            : TvApp.getApplication().getString(R.string.lbl_never);
      case SearchHint:
        return searchHint.getType();
    }

    return "";
  }
Esempio n. 3
0
  private void createPlayer(int buffer) {
    try {

      // Create a new media player
      ArrayList<String> options = new ArrayList<>(20);
      options.add("--network-caching=" + buffer);
      options.add("--no-audio-time-stretch");
      options.add("--androidwindow-chroma");
      options.add("RV32");
      //            options.add("--subsdec-encoding");
      //            options.add("Universal (UTF-8)");
      options.add("-v");

      mLibVLC = new LibVLC(options);
      TvApp.getApplication().getLogger().Info("Network buffer set to " + buffer);
      LibVLC.setOnNativeCrashListener(
          new LibVLC.OnNativeCrashListener() {
            @Override
            public void onNativeCrash() {
              new Exception().printStackTrace();
              Utils.PutCustomAcraData();
              ACRA.getErrorReporter().handleException(new Exception("Error in LibVLC"), false);
              mActivity.finish();
              android.os.Process.killProcess(android.os.Process.myPid());
              System.exit(10);
            }
          });

      mVlcPlayer = new org.videolan.libvlc.MediaPlayer(mLibVLC);
      SharedPreferences prefs = TvApp.getApplication().getPrefs();
      String audioOption =
          Utils.isFireTv() && !Utils.is50()
              ? "1"
              : prefs.getString("pref_audio_option", "0"); // force compatible audio on Fire 4.2
      mVlcPlayer.setAudioOutput(
          "0".equals(audioOption) ? "android_audiotrack" : "opensles_android");
      mVlcPlayer.setAudioOutputDevice("hdmi");

      mSurfaceHolder.addCallback(mSurfaceCallback);
      mVlcPlayer.setEventListener(mVlcHandler);
      mVlcPlayer.getVLCVout().addCallback(this);

    } catch (Exception e) {
      TvApp.getApplication().getLogger().ErrorException("Error creating VLC player", e);
      Utils.showToast(
          TvApp.getApplication(),
          TvApp.getApplication().getString(R.string.msg_video_playback_error));
    }
  }
Esempio n. 4
0
  public String getFullName() {
    switch (type) {
      case BaseItem:
      case LiveTvProgram:
      case LiveTvRecording:
        return Utils.GetFullName(baseItem);
      case Person:
        return person.getName();
      case Chapter:
        return chapterInfo.getName();
      case Server:
        return serverInfo.getName();
      case User:
        return user.getName();
      case LiveTvChannel:
        return channelInfo.getName();
      case GridButton:
        return gridButton.getText();
      case SearchHint:
        return (searchHint.getSeries() != null ? searchHint.getSeries() + " - " : "")
            + searchHint.getName();
    }

    return TvApp.getApplication().getString(R.string.lbl_bracket_unknown);
  }
Esempio n. 5
0
  public String getBackdropImageUrl() {
    switch (type) {
      case BaseItem:
        return Utils.getBackdropImageUrl(
            baseItem, TvApp.getApplication().getConnectionManager().GetApiClient(baseItem), true);
    }

    return null;
  }
Esempio n. 6
0
 public String getImageUrl(String imageType, int maxHeight) {
   switch (type) {
     case BaseItem:
     case LiveTvProgram:
     case LiveTvRecording:
       switch (imageType) {
         case tv.emby.embyatv.model.ImageType.BANNER:
           return Utils.getBannerImageUrl(
               baseItem, TvApp.getApplication().getApiClient(), maxHeight);
         case tv.emby.embyatv.model.ImageType.THUMB:
           return Utils.getThumbImageUrl(
               baseItem, TvApp.getApplication().getApiClient(), maxHeight);
         default:
           return getPrimaryImageUrl(maxHeight);
       }
     default:
       return getPrimaryImageUrl(maxHeight);
   }
 }
Esempio n. 7
0
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
   if (mVlcPlayer != null) {
     mVlcPlayer.getVLCVout().detachViews();
     mVlcPlayer.getVLCVout().setVideoView(mSurfaceView);
     if (hasSubtitlesSurface) mVlcPlayer.getVLCVout().setSubtitlesView(mSubtitlesSurface);
     mVlcPlayer.getVLCVout().attachViews();
     TvApp.getApplication().getLogger().Debug("Surface attached");
     mSurfaceReady = true;
   }
 }
Esempio n. 8
0
 public void setAudioMode() {
   if (!nativeMode) {
     SharedPreferences prefs = TvApp.getApplication().getPrefs();
     String audioOption =
         Utils.isFireTv() && !Utils.is50()
             ? "1"
             : prefs.getString("pref_audio_option", "0"); // force compatible audio on Fire 4.2
     mVlcPlayer.setAudioOutput(
         "0".equals(audioOption) ? "android_audiotrack" : "opensles_android");
     mVlcPlayer.setAudioOutputDevice("hdmi");
   }
 }
Esempio n. 9
0
  public long seekTo(long pos) {
    if (nativeMode) {
      Long intPos = pos;
      mVideoView.seekTo(intPos.intValue());
      return pos;
    } else {
      if (mVlcPlayer == null || !mVlcPlayer.isSeekable()) return -1;
      mForcedTime = pos;
      mLastTime = mVlcPlayer.getTime();
      TvApp.getApplication().getLogger().Info("VLC length in seek is: " + mVlcPlayer.getLength());
      try {
        if (getDuration() > 0) mVlcPlayer.setPosition((float) pos / getDuration());
        else mVlcPlayer.setTime(pos);

        return pos;

      } catch (Exception e) {
        TvApp.getApplication().getLogger().ErrorException("Error seeking in VLC", e);
        Utils.showToast(mActivity, "Unable to seek");
        return -1;
      }
    }
  }
Esempio n. 10
0
  public boolean setSubtitleTrack(int index, List<MediaStream> allStreams) {
    if (!nativeMode) {
      // find the relative order of our sub index within the sub tracks in VLC
      int vlcIndex = 1; // start at 1 to account for "disabled"
      for (MediaStream stream : allStreams) {
        if (stream.getType() == MediaStreamType.Subtitle && !stream.getIsExternal()) {
          if (stream.getIndex() == index) {
            break;
          }
          vlcIndex++;
        }
      }

      org.videolan.libvlc.MediaPlayer.TrackDescription vlcSub;
      try {
        vlcSub = getSubtitleTracks()[vlcIndex];

      } catch (IndexOutOfBoundsException e) {
        TvApp.getApplication()
            .getLogger()
            .Error("Could not locate subtitle with index %s in vlc track info", index);
        return false;
      } catch (NullPointerException e) {
        TvApp.getApplication()
            .getLogger()
            .Error(
                "No subtitle tracks found in player trying to set subtitle with index %s in vlc track info",
                index);
        return false;
      }

      TvApp.getApplication().getLogger().Info("Setting Vlc sub to " + vlcSub.name);
      return mVlcPlayer.setSpuTrack(vlcSub.id);
    }

    return false;
  }
Esempio n. 11
0
 public void refresh(final EmptyResponse outerResponse) {
   switch (type) {
     case BaseItem:
       TvApp.getApplication()
           .getApiClient()
           .GetItemAsync(
               getItemId(),
               TvApp.getApplication().getCurrentUser().getId(),
               new Response<BaseItemDto>() {
                 @Override
                 public void onResponse(BaseItemDto response) {
                   baseItem = response;
                   outerResponse.onResponse();
                 }
               });
       break;
     case Person:
       break;
     case Server:
       break;
     case User:
       break;
     case Chapter:
       break;
     case SearchHint:
       break;
     case LiveTvChannel:
       break;
     case LiveTvRecording:
       break;
     case GridButton:
       break;
     case LiveTvProgram:
       break;
   }
 }
Esempio n. 12
0
  public Drawable getBadgeImage() {
    switch (type) {
      case BaseItem:
        if (baseItem.getType().equals("Movie") && baseItem.getCriticRating() != null) {
          return baseItem.getCriticRating() > 59
              ? TvApp.getApplication().getDrawableCompat(R.drawable.fresh)
              : TvApp.getApplication().getDrawableCompat(R.drawable.rotten);
        }
        break;
      case Person:
        break;
      case Server:
        break;
      case User:
        if (user.getHasPassword()) {
          return TvApp.getApplication().getDrawableCompat(R.drawable.lock);
        }
        break;
      case Chapter:
        break;
    }

    return TvApp.getApplication().getDrawableCompat(R.drawable.blank10x10);
  }
Esempio n. 13
0
  public void start() {
    if (nativeMode) {
      mVideoView.start();
      mVideoView.setKeepScreenOn(true);
      normalWidth = mVideoView.getLayoutParams().width;
      normalHeight = mVideoView.getLayoutParams().height;
    } else {
      if (!mSurfaceReady) {
        TvApp.getApplication().getLogger().Error("Attempt to play before surface ready");
        return;
      }

      if (!mVlcPlayer.isPlaying()) {
        mVlcPlayer.play();
      }
    }
  }
Esempio n. 14
0
  public void setVideoPath(String path) {
    mCurrentVideoPath = path;

    if (nativeMode) {
      try {
        mVideoView.setVideoPath(path);
      } catch (IllegalStateException e) {
        TvApp.getApplication()
            .getLogger()
            .ErrorException("Unable to set video path.  Probably backing out.", e);
      }
    } else {
      mSurfaceHolder.setKeepScreenOn(true);

      mCurrentMedia = new Media(mLibVLC, Uri.parse(path));
      mCurrentMedia.parse();
      mVlcPlayer.setMedia(mCurrentMedia);

      mCurrentMedia.release();
    }
  }
Esempio n. 15
0
 public static void showWelcomeMessage() {
   if (isHalloween() && TvApp.getApplication().getCurrentActivity() != null) {
     new Handler()
         .postDelayed(
             new Runnable() {
               @Override
               public void run() {
                 MediaPlayer mp = MediaPlayer.create(TvApp.getApplication(), R.raw.howl);
                 mp.start();
                 TvApp.getApplication()
                     .getCurrentActivity()
                     .showMessage(
                         "Happy Halloween!",
                         "Try some of our spooky suggestions",
                         10000,
                         R.drawable.ghost,
                         R.drawable.orange_gradient);
               }
             },
             2000);
   }
 }
Esempio n. 16
0
  public void contractVideo(int height) {
    FrameLayout.LayoutParams lp =
        (FrameLayout.LayoutParams)
            (nativeMode ? mVideoView.getLayoutParams() : mSurfaceView.getLayoutParams());
    if (isContracted) return;

    Activity activity = TvApp.getApplication().getCurrentActivity();
    int sw = activity.getWindow().getDecorView().getWidth();
    int sh = activity.getWindow().getDecorView().getHeight();
    float ar = (float) sw / sh;
    lp.height = height;
    lp.width = (int) Math.ceil(height * ar);
    lp.rightMargin = ((lp.width - normalWidth) / 2) - 110;
    lp.bottomMargin = ((lp.height - normalHeight) / 2) - 50;

    if (nativeMode) {
      mVideoView.setLayoutParams(lp);
      mVideoView.invalidate();
    } else mSurfaceView.setLayoutParams(lp);

    isContracted = true;
  }
Esempio n. 17
0
 public String getPrimaryImageUrl(int maxHeight) {
   switch (type) {
     case BaseItem:
     case LiveTvProgram:
     case LiveTvRecording:
       return Utils.getPrimaryImageUrl(
           baseItem, TvApp.getApplication().getApiClient(), true, preferParentThumb, maxHeight);
     case Person:
       return Utils.getPrimaryImageUrl(person, TvApp.getApplication().getApiClient(), maxHeight);
     case User:
       return Utils.getPrimaryImageUrl(user, TvApp.getApplication().getLoginApiClient());
     case Chapter:
       return chapterInfo.getImagePath();
     case LiveTvChannel:
       return Utils.getPrimaryImageUrl(channelInfo, TvApp.getApplication().getApiClient());
     case Server:
       return "android.resource://tv.emby.embyatv/" + R.drawable.server;
     case GridButton:
       return "android.resource://tv.emby.embyatv/" + gridButton.getImageIndex();
     case SearchHint:
       return !Utils.IsEmpty(searchHint.getPrimaryImageTag())
           ? Utils.getImageUrl(
               searchHint.getItemId(),
               ImageType.Primary,
               searchHint.getPrimaryImageTag(),
               TvApp.getApplication().getApiClient())
           : !Utils.IsEmpty(searchHint.getThumbImageItemId())
               ? Utils.getImageUrl(
                   searchHint.getThumbImageItemId(),
                   ImageType.Thumb,
                   searchHint.getThumbImageTag(),
                   TvApp.getApplication().getApiClient())
               : null;
   }
   return null;
 }
Esempio n. 18
0
 public static int getBrandColor() {
   return isHalloween()
       ? TvApp.getApplication().getResources().getColor(R.color.halloween_end)
       : Utils.getBrandColor();
 }
/** Created by Eric on 5/4/2015. */
public class ProgramGridCell extends RelativeLayout implements IRecordingIndicatorView {

  private LiveTvGuideActivity mActivity;
  private TextView mProgramName;
  private LinearLayout mInfoRow;
  private ProgramInfoDto mProgram;
  private ImageView mRecIndicator;
  private int mBackgroundColor = 0;
  private final int IND_HEIGHT = Utils.convertDpToPixel(TvApp.getApplication(), 10);

  public ProgramGridCell(Context context, ProgramInfoDto program) {
    super(context);
    initComponent((LiveTvGuideActivity) context, program);
  }

  private void initComponent(LiveTvGuideActivity activity, ProgramInfoDto program) {
    mActivity = activity;
    mProgram = program;
    LayoutInflater inflater = LayoutInflater.from(activity);
    View v = inflater.inflate(R.layout.program_grid_cell, this, false);
    this.addView(v);

    mProgramName = (TextView) findViewById(R.id.programName);
    mInfoRow = (LinearLayout) findViewById(R.id.infoRow);
    mProgramName.setText(program.getName());
    mProgram = program;
    mProgramName.setFocusable(false);
    mInfoRow.setFocusable(false);
    mRecIndicator = (ImageView) findViewById(R.id.recIndicator);

    if (program.getIsMovie()) mBackgroundColor = getResources().getColor(R.color.guide_movie_bg);
    else if (program.getIsNews()) mBackgroundColor = getResources().getColor(R.color.guide_news_bg);
    else if (program.getIsSports())
      mBackgroundColor = getResources().getColor(R.color.guide_sports_bg);
    else if (program.getIsKids()) mBackgroundColor = getResources().getColor(R.color.guide_kids_bg);

    setBackgroundColor(mBackgroundColor);

    if (program.getStartDate() != null && program.getEndDate() != null) {
      TextView time = new TextView(activity);
      Date localStart = Utils.convertToLocalDate(program.getStartDate());
      if (localStart.getTime() + 60000 < activity.getCurrentLocalStartDate())
        mProgramName.setText("<< " + mProgramName.getText());
      time.setText(
          android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                  .format(Utils.convertToLocalDate(program.getStartDate()))
              + "-"
              + android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                  .format(Utils.convertToLocalDate(program.getEndDate())));
      mInfoRow.addView(time);
    }

    if (program.getOfficialRating() != null && !program.getOfficialRating().equals("0")) {
      InfoLayoutHelper.addSpacer(activity, mInfoRow, "  ", 10);
      InfoLayoutHelper.addBlockText(activity, mInfoRow, program.getOfficialRating(), 10);
    }

    if (program.getIsHD() != null && program.getIsHD()) {
      InfoLayoutHelper.addSpacer(activity, mInfoRow, "  ", 10);
      InfoLayoutHelper.addBlockText(activity, mInfoRow, "HD", 10);
    }

    if (program.getSeriesTimerId() != null) {
      mRecIndicator.setImageResource(R.drawable.recseries);
    } else if (program.getTimerId() != null) {
      mRecIndicator.setImageResource(R.drawable.rec);
    }

    setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            mActivity.showProgramOptions();
          }
        });
  }

  @Override
  protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
    super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);

    if (gainFocus) {
      setBackgroundColor(getResources().getColor(R.color.lb_default_brand_color));
      mActivity.setSelectedProgram(this);
    } else {
      setBackgroundColor(mBackgroundColor);
    }

    // TvApp.getApplication().getLogger().Debug("Focus on "+mProgram.getName()+ " was " +(gainFocus
    // ? "gained" : "lost"));
  }

  public ProgramInfoDto getProgram() {
    return mProgram;
  }

  public void setRecTimer(String id) {
    mProgram.setTimerId(id);
    mRecIndicator.setImageResource(id != null ? R.drawable.rec : R.drawable.blank10x10);
  }

  public void setRecSeriesTimer(String id) {
    mProgram.setSeriesTimerId(id);
    mRecIndicator.setImageResource(id != null ? R.drawable.recseries : R.drawable.blank10x10);
  }
}
  private void initComponent(LiveTvGuideActivity activity, ProgramInfoDto program) {
    mActivity = activity;
    mProgram = program;
    LayoutInflater inflater = LayoutInflater.from(activity);
    View v = inflater.inflate(R.layout.program_grid_cell, this, false);
    this.addView(v);

    mProgramName = (TextView) findViewById(R.id.programName);
    mInfoRow = (LinearLayout) findViewById(R.id.infoRow);
    mProgramName.setText(program.getName());
    mProgram = program;
    mProgramName.setFocusable(false);
    mInfoRow.setFocusable(false);
    mRecIndicator = (ImageView) findViewById(R.id.recIndicator);

    if (program.getIsMovie()) mBackgroundColor = getResources().getColor(R.color.guide_movie_bg);
    else if (program.getIsNews()) mBackgroundColor = getResources().getColor(R.color.guide_news_bg);
    else if (program.getIsSports())
      mBackgroundColor = getResources().getColor(R.color.guide_sports_bg);
    else if (program.getIsKids()) mBackgroundColor = getResources().getColor(R.color.guide_kids_bg);

    setBackgroundColor(mBackgroundColor);

    if (program.getStartDate() != null && program.getEndDate() != null) {
      TextView time = new TextView(activity);
      Date localStart = Utils.convertToLocalDate(program.getStartDate());
      if (localStart.getTime() + 60000 < activity.getCurrentLocalStartDate())
        mProgramName.setText("<< " + mProgramName.getText());
      time.setText(
          android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                  .format(Utils.convertToLocalDate(program.getStartDate()))
              + "-"
              + android.text.format.DateFormat.getTimeFormat(TvApp.getApplication())
                  .format(Utils.convertToLocalDate(program.getEndDate())));
      mInfoRow.addView(time);
    }

    if (program.getOfficialRating() != null && !program.getOfficialRating().equals("0")) {
      InfoLayoutHelper.addSpacer(activity, mInfoRow, "  ", 10);
      InfoLayoutHelper.addBlockText(activity, mInfoRow, program.getOfficialRating(), 10);
    }

    if (program.getIsHD() != null && program.getIsHD()) {
      InfoLayoutHelper.addSpacer(activity, mInfoRow, "  ", 10);
      InfoLayoutHelper.addBlockText(activity, mInfoRow, "HD", 10);
    }

    if (program.getSeriesTimerId() != null) {
      mRecIndicator.setImageResource(R.drawable.recseries);
    } else if (program.getTimerId() != null) {
      mRecIndicator.setImageResource(R.drawable.rec);
    }

    setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            mActivity.showProgramOptions();
          }
        });
  }
Esempio n. 21
0
  private void changeSurfaceLayout(
      int videoWidth,
      int videoHeight,
      int videoVisibleWidth,
      int videoVisibleHeight,
      int sarNum,
      int sarDen) {
    int sw;
    int sh;

    // get screen size
    Activity activity = TvApp.getApplication().getCurrentActivity();
    if (activity == null) return; // called during destroy
    sw = activity.getWindow().getDecorView().getWidth();
    sh = activity.getWindow().getDecorView().getHeight();

    double dw = sw, dh = sh;
    boolean isPortrait;

    isPortrait =
        mActivity.getResources().getConfiguration().orientation
            == Configuration.ORIENTATION_PORTRAIT;

    if (sw > sh && isPortrait || sw < sh && !isPortrait) {
      dw = sh;
      dh = sw;
    }

    // sanity check
    if (dw * dh == 0 || videoWidth * videoHeight == 0) {
      TvApp.getApplication().getLogger().Error("Invalid surface size");
      return;
    }

    // compute the aspect ratio
    double ar, vw;
    if (sarDen == sarNum) {
      /* No indication about the density, assuming 1:1 */
      vw = videoVisibleWidth;
      ar = (double) videoVisibleWidth / (double) videoVisibleHeight;
    } else {
      /* Use the specified aspect ratio */
      vw = videoVisibleWidth * (double) sarNum / sarDen;
      ar = vw / videoVisibleHeight;
    }

    // compute the display aspect ratio
    double dar = dw / dh;

    if (dar < ar) dh = dw / ar;
    else dw = dh * ar;

    // set display size
    ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
    lp.width = (int) Math.ceil(dw * videoWidth / videoVisibleWidth);
    lp.height = (int) Math.ceil(dh * videoHeight / videoVisibleHeight);
    normalWidth = lp.width;
    normalHeight = lp.height;
    mSurfaceView.setLayoutParams(lp);
    if (hasSubtitlesSurface) mSubtitlesSurface.setLayoutParams(lp);

    // set frame size (crop if necessary)
    if (mSurfaceFrame != null) {
      lp = mSurfaceFrame.getLayoutParams();
      lp.width = (int) Math.floor(dw);
      lp.height = (int) Math.floor(dh);
      mSurfaceFrame.setLayoutParams(lp);
    }

    TvApp.getApplication().getLogger().Debug("Surface sized " + mVideoWidth + "x" + mVideoHeight);
    mSurfaceView.invalidate();
    if (hasSubtitlesSurface) mSubtitlesSurface.invalidate();
  }