Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Introduce support for Live-VOD mode for live streams #155

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ public class DefaultPlayerUIController implements PlayerUIController, YouTubePla
private boolean showPlayPauseButton = true;
private boolean showBufferingProgress = true;

private boolean isLive = false;
private boolean isLiveVOD = false;
private float videoDurationValue = 0;

public DefaultPlayerUIController(@NonNull YouTubePlayerView youTubePlayerView, @NonNull YouTubePlayer youTubePlayer) {
this.youTubePlayerView = youTubePlayerView;
this.youTubePlayer = youTubePlayer;
Expand Down Expand Up @@ -108,6 +112,7 @@ private void initViews(View controlsView) {
playPauseButton.setOnClickListener(this);
menuButton.setOnClickListener(this);
fullScreenButton.setOnClickListener(this);
liveVideoIndicator.setOnClickListener(this);
}

@Override
Expand Down Expand Up @@ -139,12 +144,15 @@ public void showPlayPauseButton(boolean show) {

@Override
public void enableLiveVideoUI(boolean enable) {
isLive = enable;
enableLiveVODUI(false);
if(enable) {
videoDuration.setVisibility(View.INVISIBLE);
seekBar.setVisibility(View.INVISIBLE);
videoCurrentTime.setVisibility(View.INVISIBLE);

liveVideoIndicator.setVisibility(View.VISIBLE);
liveVideoIndicator.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_live_dot_red,0,0,0);
liveVideoIndicator.setCompoundDrawablePadding((int) youTubePlayerView.getContext().getResources().getDimension(R.dimen._8dp));
} else {
videoDuration.setVisibility(View.VISIBLE);
seekBar.setVisibility(View.VISIBLE);
Expand All @@ -154,6 +162,24 @@ public void enableLiveVideoUI(boolean enable) {
}
}

/**
* This is the case when user manually changes the seekbar position during a live stream.
* In this case, the player switches to a Live-VOD (Video-On-Demand) mode.
* UI changes are made on 1) Live video indicator tag, 2) Seekbar behaviour.
* This is in sync with the standard behaviour inside youtube app.
*
*/
private void enableLiveVODUI(boolean enable) {
isLiveVOD = enable;
if (enable) {
liveVideoIndicator.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_live_dot_white,0,0,0);
videoCurrentTime.setVisibility(View.VISIBLE);
} else {
liveVideoIndicator.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_live_dot_red,0,0,0);
videoCurrentTime.setVisibility(View.INVISIBLE);
}
}

/**
* Set custom action to the left of the Play/Pause button
*/
Expand Down Expand Up @@ -266,6 +292,20 @@ else if(view == fullScreenButton)
onFullScreenButtonPressed();
else if(view == menuButton)
onMenuButtonPressed();
else if (view == liveVideoIndicator)
onLiveVideoIndicatorPressed();
}

/**
* During a live session when user switches to VOD mode by moving the seekbar,
* this allows the user to get back to the live mode instantly.
* This is in sync with the default youtube app behaviour
*/
private void onLiveVideoIndicatorPressed() {
enableLiveVideoUI(true);
if (videoDurationValue != 0)
youTubePlayer.seekTo(videoDurationValue);
seekBar.setProgress(Math.round(videoDurationValue));
}

private void onMenuButtonPressed() {
Expand Down Expand Up @@ -442,6 +482,7 @@ public void onCurrentSecond(float second) {

@Override
public void onVideoDuration(float duration) {
videoDurationValue = duration;
videoDuration.setText(Utils.formatTime(duration));
seekBar.setMax((int) duration);
}
Expand Down Expand Up @@ -479,13 +520,45 @@ public void onClick(View view) {

@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
videoCurrentTime.setText(Utils.formatTime(i));
if (isLive) {
handleProgressChangedDuringLive(seekBar,i);
} else {
videoCurrentTime.setText(Utils.formatTime(i));
}
}

/**
* This handles the case when progress changes during Live stream.
* There are two scenarios being handled here a) Live b) Live-VOD.
* a) In case of Live, we maintain the seekbar to the value same same as duration.
* b) In case of Live-VOD, the current time is updated to show the negative value of
* current time, which lets user know how far they're behind the Live stream.
*
* Both a) & b) are in sync with default youtube app behaviour.
*
*/
private void handleProgressChangedDuringLive(SeekBar seekBar, int i) {
// Can't do much without video duration value
if (videoDurationValue == 0)
return;

if (i == videoDurationValue) {
enableLiveVideoUI(true);
return;
}
if (isLiveVOD) {
String currentTime = "-" + Utils.formatTime(videoDurationValue - i);
videoCurrentTime.setText(currentTime);
} else {
seekBar.setProgress(Math.round(videoDurationValue));
}
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
seekBarTouchStarted = true;
}
if (isLive)
enableLiveVODUI(true);
seekBarTouchStarted = true; }

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/res/drawable/ic_live_dot_red.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#F44336" />
<size
android:width="8dp"
android:height="8dp" />
</shape>
8 changes: 8 additions & 0 deletions core/src/main/res/drawable/ic_live_dot_white.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF" />
<size
android:width="8dp"
android:height="8dp" />
</shape>