org.videolan.vlc.gui.helpers.AsyncImageLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.videolan.vlc.gui.helpers.AsyncImageLoader.java

Source

/*
 * *************************************************************************
 *  AsyncImageLoader.java
 * **************************************************************************
 *  Copyright  2015 VLC authors and VideoLAN
 *  Author: Geoffrey Mtais
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *  ***************************************************************************
 */

package org.videolan.vlc.gui.helpers;

import android.databinding.BindingAdapter;
import android.databinding.DataBindingUtil;
import android.databinding.OnRebindCallback;
import android.databinding.ViewDataBinding;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import org.videolan.medialibrary.media.MediaLibraryItem;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.BR;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.media.MediaGroup;
import org.videolan.vlc.util.HttpImageLoader;
import org.videolan.vlc.util.Strings;

public class AsyncImageLoader {

    public interface Callbacks {
        Bitmap getImage();

        void updateImage(Bitmap bitmap, View target);
    }

    public final static String TAG = "VLC/AsyncImageLoader";
    private static final Handler sHandler = new Handler(Looper.getMainLooper());

    public static final Bitmap DEFAULT_COVER_VIDEO = BitmapCache.getFromResource(VLCApplication.getAppResources(),
            R.drawable.ic_no_thumbnail_1610);
    public static final BitmapDrawable DEFAULT_COVER_VIDEO_DRAWABLE = new BitmapDrawable(
            VLCApplication.getAppResources(), DEFAULT_COVER_VIDEO);
    public static final Bitmap DEFAULT_COVER_AUDIO = BitmapCache.getFromResource(VLCApplication.getAppResources(),
            R.drawable.ic_no_song);
    public static final BitmapDrawable DEFAULT_COVER_AUDIO_DRAWABLE = new BitmapDrawable(
            VLCApplication.getAppResources(), DEFAULT_COVER_AUDIO);
    public static final BitmapDrawable DEFAULT_COVER_ARTIST_DRAWABLE = new BitmapDrawable(
            VLCApplication.getAppResources(),
            BitmapCache.getFromResource(VLCApplication.getAppResources(), R.drawable.ic_no_artist));
    public static final BitmapDrawable DEFAULT_COVER_ALBUM_DRAWABLE = new BitmapDrawable(
            VLCApplication.getAppResources(),
            BitmapCache.getFromResource(VLCApplication.getAppResources(), R.drawable.ic_no_album));

    /*
     * Custom bindings to trigger image (down)loading
     */

    @BindingAdapter({ "imageUri" })
    public static void downloadIcon(final View v, final Uri imageUri) {
        AsyncImageLoader.LoadImage(new CoverFetcher(null) {
            @Override
            public Bitmap getImage() {
                return HttpImageLoader.downloadBitmap(imageUri.toString());
            }

            @Override
            public void updateImage(Bitmap bitmap, View target) {
                updateTargetImage(bitmap, v, binding);
            }
        }, v);
    }

    @BindingAdapter({ "media" })
    public static void loadPicture(View v, MediaLibraryItem item) {
        if (item == null || TextUtils.isEmpty(item.getArtworkMrl())
                || item.getItemType() == MediaLibraryItem.TYPE_GENRE
                || item.getItemType() == MediaLibraryItem.TYPE_PLAYLIST)
            return;
        final Bitmap bitmap = BitmapCache.getInstance().getBitmapFromMemCache(item.getArtworkMrl());
        if (bitmap != null) {
            updateTargetImage(bitmap, v, DataBindingUtil.findBinding(v));
            return;
        }
        if (item.getItemType() == MediaLibraryItem.TYPE_MEDIA) {
            if (item instanceof MediaGroup)
                item = ((MediaGroup) item).getFirstMedia();
            int type = ((MediaWrapper) item).getType();
            boolean isMedia = type == MediaWrapper.TYPE_AUDIO || type == MediaWrapper.TYPE_VIDEO;
            Uri uri = ((MediaWrapper) item).getUri();
            if (!isMedia && !(type == MediaWrapper.TYPE_DIR && "upnp".equals(uri.getScheme())))
                return;
            if (item.getId() == 0L && (isMedia) && "file".equals(uri.getScheme())) {
                MediaWrapper mw = VLCApplication.getMLInstance().getMedia(uri);
                if (mw != null)
                    item = mw;
            }
        }
        AsyncImageLoader.LoadImage(new MLItemCoverFetcher(v, item), v);
    }

    public static void LoadImage(final Callbacks cbs, final View target) {
        VLCApplication.runBackground(new Runnable() {
            @Override
            public void run() {
                final Bitmap bitmap = cbs.getImage();
                cbs.updateImage(bitmap, target);
            }
        });
    }

    private static class MLItemCoverFetcher extends AsyncImageLoader.CoverFetcher {
        MediaLibraryItem item;
        int width;

        MLItemCoverFetcher(View v, MediaLibraryItem item) {
            super(DataBindingUtil.findBinding(v));
            this.item = item;
            width = v.getWidth();
        }

        @Override
        public Bitmap getImage() {
            if (bindChanged)
                return null;
            String artworkUrl = item.getArtworkMrl();
            if (!TextUtils.isEmpty(artworkUrl) && artworkUrl.startsWith("http"))
                return HttpImageLoader.downloadBitmap(artworkUrl);
            return AudioUtil.readCoverBitmap(Strings.removeFileProtocole(item.getArtworkMrl()), width);
        }

        @Override
        public void updateImage(Bitmap bitmap, View target) {
            if (!bindChanged)
                updateTargetImage(bitmap, target, binding);
        }
    }

    private static void updateTargetImage(final Bitmap bitmap, final View target, final ViewDataBinding vdb) {
        if (bitmap == null || bitmap.getWidth() <= 1 || bitmap.getHeight() <= 1)
            return;
        if (vdb != null) {
            vdb.setVariable(BR.scaleType, ImageView.ScaleType.FIT_CENTER);
            vdb.setVariable(BR.cover, new BitmapDrawable(VLCApplication.getAppResources(), bitmap));
            vdb.setVariable(BR.protocol, null);
        } else {
            sHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (target instanceof ImageView) {
                        ImageView iv = (ImageView) target;
                        iv.setVisibility(View.VISIBLE);
                        iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
                        iv.setImageBitmap(bitmap);
                    } else if (target instanceof TextView) {
                        ViewCompat.setBackground(target,
                                new BitmapDrawable(VLCApplication.getAppResources(), bitmap));
                        ((TextView) target).setText(null);
                    }
                }
            });
        }
    }

    abstract static class CoverFetcher implements AsyncImageLoader.Callbacks {
        protected ViewDataBinding binding = null;
        boolean bindChanged = false;
        final OnRebindCallback<ViewDataBinding> rebindCallbacks = new OnRebindCallback<ViewDataBinding>() {
            @Override
            public boolean onPreBind(ViewDataBinding binding) {
                bindChanged = true;
                return super.onPreBind(binding);
            }

            @Override
            public void onCanceled(ViewDataBinding binding) {
                super.onCanceled(binding);
            }

            @Override
            public void onBound(ViewDataBinding binding) {
                super.onBound(binding);
            }
        };

        CoverFetcher(ViewDataBinding binding) {
            if (binding != null) {
                this.binding = binding;
                this.binding.executePendingBindings();
                this.binding.addOnRebindCallback(rebindCallbacks);
            }
        }
    }
}