eneim / toro

Video list auto playback made simple, specially built for RecyclerView
Apache License 2.0
1.42k stars 252 forks source link

Mute / Unmute Audio #330

Open ksi3321 opened 6 years ago

ksi3321 commented 6 years ago

Hi eneim Thanks for your wonderful library. I am currently using version 3.4.2

I have declared these on my app gradle

implementation "im.ene.toro3:toro:3.4.2"
implementation "im.ene.toro3:toro-ext-exoplayer:3.4.2"

I am able to play videos on the recyclerview which works fine. But I have been trying another requirement which is to mute the audio of the video view. I tried doing the following:

if (!ImageviewModel.mute.get()) {
                ImageviewModel.mute.set(false);
                helper.getVolumeInfo().setVolume(1.0f);
} else {
                ImageviewModel.mute.set(true);
                helper.getVolumeInfo().setVolume(0.0f);
}

and also this:

if (!ImageviewModel.mute.get()) {
                ImageviewModel.mute.set(false);
                helper.getVolumeInfo().setMute(false);
} else {
                ImageviewModel.mute.set(true);
                 helper.getVolumeInfo().setMute(true); 
}

I see that the audio is still heard and is not muted. Can you tell me why this is happening? I would like play videos by muting or unmuting the audio. Here is my adapter code:

public class RecyclerViewItemAdapter extends RecyclerView.Adapter<BaseViewHolder> {
   public static final int VIEW_STORY_HEADER = 0;
   public static final int VIEW_IMAGE_ITEM = 1;

    private List<ImageItem> mItemsList;
    private List<Integer> sampleBanners = new ArrayList<>();

    HeaderItemAdapter mAdapter;

    public void setHeaderItemAdapter(HeaderItemAdapter mAdapter) {
        this.mAdapter = mAdapter;
    }

    LinearLayoutManager mLayoutManager;

    FragmentManager manager;

    int[] sampleImages = {R.drawable.image1,
                          R.drawable.image2,
                          R.drawable.image3};

    Context context;

    public void setContext(Context context, FragmentManager manager) {
        this.context = context;
        this.manager = manager;
    }

    public RecyclerViewItemAdapter(List<ImageItem> mItemsList) {
        this.mItemsList = mItemsList;

        this.mLayoutManager = new LinearLayoutManager(context);
    }

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
               ItemImageBinding ItemImageBinding =
                       ItemImageBinding.inflate(LayoutInflater.from(parent.getContext()),
                                parent, false);

                return newItemViewHolderr(itemImageItemImageBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        holder.onBind(position);
    }

    @Override
    public int getItemCount() {
        if (mItemsList != null && mItemsList.size() > 0) {
            return mItemsList.size();
        } else {
            return 0;
        }
    }

    public void clearAll() {
        mItemsList.clear();
    }

    public void addItems(List<ImageItem> feedsList) {
        mItemsList.addAll(feedsList);
        notifyDataSetChanged();
    }

    public class ItemViewHolder extends BaseViewHolder
            implements ImageviewModel.ImageItemItemListener, ImageListener,ToroPlayer {

        final ItemImageBinding mBinding;

        ImageviewModel ImageviewModel;
        @Nullable
        ExoPlayerViewHelper helper;
        @Nullable private Uri mediaUri;

    private Playable.EventListener listener = new Playable.EventListener(){

    @Override
    public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {

    }

    @Override
    public void onRenderedFirstFrame() {

        helper.pause();

    }

    @Override
    public void onCues(List<Cue> cues) {

    }

    @Override
    public void onMetadata(Metadata metadata) {

    }

    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {

    }

    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

    }

    @Override
    public void onLoadingChanged(boolean isLoading) {

    }

    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {

    }

    @Override
    public void onRepeatModeChanged(int repeatMode) {

    }

    @Override
    public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

    }

    @Override
    public void onPlayerError(ExoPlaybackException error) {

    }

    @Override
    public void onPositionDiscontinuity(int reason) {

    }

    @Override
    public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

    }

    @Override
    public void onSeekProcessed() {

    }

};

        public ItemViewHolder(ItemImageItemImageBinding mBinding) {
            super(mBinding.getRoot());
            this.mBinding = mBinding;

        }

        @Override
        public void onBind(int position) {

            final ImageItem feed = mItemsList.get(position);

            ImageviewModel = new ImageviewModel(feed, this);

            mBinding.setViewModel(ImageviewModel);

                mediaUri = Uri.parse("my url");
                mBinding.executePendingBindings();

        }

        @Override
        public void onVideoPlayClicked()
        {

            if(helper.isPlaying())
            {
                helper.pause();
            }
            else
            {
                helper.play();

            }
            ImageviewModel.play.set(helper.isPlaying());
        }

        @Override
        public void onMuteClicked()
        {
            if(!ImageviewModel.mute.get())
            {
                ImageviewModel.mute.set(false);
                helper.getVolumeInfo().setVolume(1.0f);
            }
            else
            {
                ImageviewModel.mute.set(true);
                helper.getVolumeInfo().setVolume(0.0f);

            }
        }

        @NonNull
        @Override
        public View getPlayerView() {
            return  mBinding.fbVideoPlayer;
        }

        @NonNull
        @Override
        public PlaybackInfo getCurrentPlaybackInfo() {
            return helper != null ? helper.getLatestPlaybackInfo() : new PlaybackInfo();
        }

        @Override
        public void initialize(@NonNull Container container, @Nullable PlaybackInfo playbackInfo) {

            if (mediaUri == null) throw new IllegalStateException("mediaUri is null.");
            if (helper == null) {
                helper = new ExoPlayerViewHelper(this, mediaUri);
                helper.addEventListener(listener);
            }
            helper.initialize(container, playbackInfo);
            helper.getVolumeInfo().setMute(false);
        }

        @Override public void play() {
            if (helper != null) helper.play();
        }

        @Override public void pause() {
            if (helper != null) helper.pause();
        }

        @Override public boolean isPlaying() {
            return helper != null && helper.isPlaying();
        }

        @Override public void release() {
            if (helper != null) {
                helper.removeEventListener(listener);
                helper.release();
                helper = null;
            }
        }

        @Override
        public boolean wantsToPlay() {
            return ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.85;
        }

        @Override
        public int getPlayerOrder() {
            return getAdapterPosition();
        }

        @Override
        public void onSettled(Container container) {

        }

    }

}
eneim commented 6 years ago

@maximus9600 Thanks for using Toro. I understand the requirement around setting volume. Next version will comes with demo and guideline as well. At the mean time, I will double check your question later and give some advice, please stay tune.

ksi3321 commented 6 years ago

Thank you for your reply @eneim . Since i had to figure out soon due to lack of time , i implemented my requirement in the following way:

@Override public void onMuteClicked() { if(!ImageViewModel.mute.get()) { ImageViewModel.mute.set(false); helper.setVolumeInfo(new VolumeInfo(false, 1.0f); } else { ImageViewModel.mute.set(true); helper.setVolumeInfo(new VolumeInfo(true, 0.0f); } }

eneim commented 6 years ago

@maximus9600 Got the situation. This link is how I implement to include volume update for mopub extension (mopub uses an older version of ExoPlayer, therefore requires a separated extension).

Long story short: this work requires to have PlayerView and ControllerView to be updated as well. But the core idea is as below:

[1] Allow your user to change the Volume from UI (click button to mute/un-mute, and drag the seekbar to change volume).

[2] In your listener, other than update the UI to match the Volume condition, you should update the PlaybackInfo's volume info by using OnVolumeChangeListener. By default, PlaybackInfo doesn't have anything about volume, so you need to extend it to include VolumeInfo value (see my demo above, and related classes as well). Also, VolumeAwareHelper shows you how to use the helper with OnVolumeChangeListener to get volume update.

[3] Deal with save/restore the PlaybackInfo on config change or ViewHolder detach/attach. The class VolumeAwareHelper and VideoViewHolder in demo above are how I'm doing it.

You can take a look and see if it can help you. In sort: extend PlaybackInfo to VolumeAwarePlaybackInfo (see source code), implement VolumeAwareHelper and register OnVolumeChangeListener (see source code), implement your ViewHolder's ToroPlayer to use the VolumeInfo. This should not be too complicated, but still, and can be less painful in near future :D.

ksi3321 commented 6 years ago

Wow. Let me try this. thanks @eneim :)

ritesh94 commented 6 years ago

Guys, I did it in the below way and its working:

if (videoHolder.helper != null) {
     if (videoHolder.helper.getVolume() == 0) {
           videoHolder.helper.setVolume(1);
     } else {
          videoHolder.helper.setVolume(0);
     }
}