<commit_before>/*
 * Copyright (C) 2010-2015 The MPDroid Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.namelessdev.mpdroid.fragments;

import com.anpmech.mpd.MPD;
import com.anpmech.mpd.exception.MPDException;
import com.anpmech.mpd.item.Album;
import com.anpmech.mpd.item.Artist;
import com.anpmech.mpd.item.Music;
import com.anpmech.mpd.item.PlaylistFile;
import com.anpmech.mpd.subsystem.status.MPDStatus;
import com.anpmech.mpd.subsystem.status.MPDStatusMap;
import com.melnykov.fab.FloatingActionButton;
import com.namelessdev.mpdroid.R;
import com.namelessdev.mpdroid.adapters.ArrayAdapter;
import com.namelessdev.mpdroid.helpers.AlbumCoverDownloadListener;
import com.namelessdev.mpdroid.helpers.AlbumInfo;
import com.namelessdev.mpdroid.helpers.CoverAsyncHelper;
import com.namelessdev.mpdroid.helpers.CoverInfo;
import com.namelessdev.mpdroid.helpers.CoverManager;
import com.namelessdev.mpdroid.library.SimpleLibraryActivity;
import com.namelessdev.mpdroid.tools.Tools;
import com.namelessdev.mpdroid.ui.ToolbarHelper;
import com.namelessdev.mpdroid.views.SongDataBinder;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.StringRes;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.PopupMenuCompat;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.io.IOException;
import java.util.Collections;

public class SongsFragment extends BrowseFragment<Music> {

    public static final String COVER_THUMBNAIL_BUNDLE_KEY = "CoverThumbnailBundle";

    public static final String COVER_TRANSITION_NAME_BASE = "cover";

    private static final String STATE_FIRST_REFRESH = "firstRefresh";

    private static final String STATE_VIEW_TRANSITION_NAME = "viewTransitionName";

    private static final String TAG = "SongsFragment";

    Album mAlbum;

    ImageButton mAlbumMenu;

    ImageView mCoverArt;

    ProgressBar mCoverArtProgress;

    CoverAsyncHelper mCoverHelper;

    Bitmap mCoverThumbnailBitmap;

    boolean mFirstRefresh;

    Handler mHandler;

    TextView mHeaderAlbum;

    TextView mHeaderArtist;

    TextView mHeaderInfo;

    Toolbar mHeaderToolbar;

    View mTracksInfoContainer;

    String mViewTransitionName;

    private AlbumCoverDownloadListener mCoverArtListener;

    private PopupMenu mCoverPopupMenu;

    public SongsFragment() {
        super(R.string.addSong, R.string.songAdded);
        mHandler = new Handler();
        mFirstRefresh = true;
    }

    @Override
    protected void add(final Music item, final boolean replace, final boolean play) {
        try {
            mApp.getMPD().add(item, replace, play);
            Tools.notifyUser(R.string.songAdded, item.getTitle(), item.getName());
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add, remove, play.", e);
        }
    }

    @Override
    protected void add(final Music item, final PlaylistFile playlist) {
        try {
            mApp.getMPD().addToPlaylist(playlist, item);
            Tools.notifyUser(mIrAdded, item);
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add to playlist.", e);
        }
    }

    private void applyPaletteWithBitmapAsync(final Bitmap bitmap) {
        final Palette.PaletteAsyncListener paletteAsyncListener =
                new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(final Palette palette) {
                        try {
                            final Palette.Swatch vibrantColor = palette.getDarkVibrantSwatch();
                            final Palette.Swatch mutedColor = palette.getVibrantSwatch();

                            if (mTracksInfoContainer != null && vibrantColor != null
                                    && !isDetached()) {
                                final int bodyTextColor = vibrantColor.getBodyTextColor();

                                mTracksInfoContainer.setBackgroundColor(vibrantColor.getRgb());
                                mHeaderAlbum.setTextColor(bodyTextColor);
                                mHeaderArtist.setTextColor(bodyTextColor);
                                mHeaderInfo.setTextColor(bodyTextColor);
                            }

                            if (mutedColor != null && mAlbumMenu instanceof FloatingActionButton) {
                                ((FloatingActionButton) mAlbumMenu)
                                        .setColorNormal(mutedColor.getRgb());
                            }
                        } catch (final NullPointerException | IllegalStateException e) {
                            Log.e(TAG, "Error while applying generated album art palette colors",
                                    e);
                        }
                    }
                };

        mApp.getAsyncHelper().execAsync(new Runnable() {
            @Override
            public void run() {
                final Palette.Builder builder = new Palette.Builder(bitmap);
                builder.generate(paletteAsyncListener);
            }
        });
    }

    @Override
    public void asyncUpdate() {
        try {
            if (getActivity() != null) {
                replaceItems(mApp.getMPD().getSongs(mAlbum));
                Collections.sort(mItems);
            }
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to async update.", e);
        }
    }

    @Override
    protected boolean forceEmptyView() {<commit_msg>SongsFragment: Suppress a crash caused by palette building during recycling.<commit_after>/*
 * Copyright (C) 2010-2015 The MPDroid Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.namelessdev.mpdroid.fragments;

import com.anpmech.mpd.MPD;
import com.anpmech.mpd.exception.MPDException;
import com.anpmech.mpd.item.Album;
import com.anpmech.mpd.item.Artist;
import com.anpmech.mpd.item.Music;
import com.anpmech.mpd.item.PlaylistFile;
import com.anpmech.mpd.subsystem.status.MPDStatus;
import com.anpmech.mpd.subsystem.status.MPDStatusMap;
import com.melnykov.fab.FloatingActionButton;
import com.namelessdev.mpdroid.R;
import com.namelessdev.mpdroid.adapters.ArrayAdapter;
import com.namelessdev.mpdroid.helpers.AlbumCoverDownloadListener;
import com.namelessdev.mpdroid.helpers.AlbumInfo;
import com.namelessdev.mpdroid.helpers.CoverAsyncHelper;
import com.namelessdev.mpdroid.helpers.CoverInfo;
import com.namelessdev.mpdroid.helpers.CoverManager;
import com.namelessdev.mpdroid.library.SimpleLibraryActivity;
import com.namelessdev.mpdroid.tools.Tools;
import com.namelessdev.mpdroid.ui.ToolbarHelper;
import com.namelessdev.mpdroid.views.SongDataBinder;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.StringRes;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.PopupMenuCompat;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.io.IOException;
import java.util.Collections;

public class SongsFragment extends BrowseFragment<Music> {

    public static final String COVER_THUMBNAIL_BUNDLE_KEY = "CoverThumbnailBundle";

    public static final String COVER_TRANSITION_NAME_BASE = "cover";

    private static final String STATE_FIRST_REFRESH = "firstRefresh";

    private static final String STATE_VIEW_TRANSITION_NAME = "viewTransitionName";

    private static final String TAG = "SongsFragment";

    Album mAlbum;

    ImageButton mAlbumMenu;

    ImageView mCoverArt;

    ProgressBar mCoverArtProgress;

    CoverAsyncHelper mCoverHelper;

    Bitmap mCoverThumbnailBitmap;

    boolean mFirstRefresh;

    Handler mHandler;

    TextView mHeaderAlbum;

    TextView mHeaderArtist;

    TextView mHeaderInfo;

    Toolbar mHeaderToolbar;

    View mTracksInfoContainer;

    String mViewTransitionName;

    private AlbumCoverDownloadListener mCoverArtListener;

    private PopupMenu mCoverPopupMenu;

    public SongsFragment() {
        super(R.string.addSong, R.string.songAdded);
        mHandler = new Handler();
        mFirstRefresh = true;
    }

    @Override
    protected void add(final Music item, final boolean replace, final boolean play) {
        try {
            mApp.getMPD().add(item, replace, play);
            Tools.notifyUser(R.string.songAdded, item.getTitle(), item.getName());
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add, remove, play.", e);
        }
    }

    @Override
    protected void add(final Music item, final PlaylistFile playlist) {
        try {
            mApp.getMPD().addToPlaylist(playlist, item);
            Tools.notifyUser(mIrAdded, item);
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add to playlist.", e);
        }
    }

    private void applyPaletteWithBitmapAsync(final Bitmap bitmap) {
        final Palette.PaletteAsyncListener paletteAsyncListener =
                new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(final Palette palette) {
                        try {
                            final Palette.Swatch vibrantColor = palette.getDarkVibrantSwatch();
                            final Palette.Swatch mutedColor = palette.getVibrantSwatch();

                            if (mTracksInfoContainer != null && vibrantColor != null
                                    && !isDetached()) {
                                final int bodyTextColor = vibrantColor.getBodyTextColor();

                                mTracksInfoContainer.setBackgroundColor(vibrantColor.getRgb());
                                mHeaderAlbum.setTextColor(bodyTextColor);
                                mHeaderArtist.setTextColor(bodyTextColor);
                                mHeaderInfo.setTextColor(bodyTextColor);
                            }

                            if (mutedColor != null && mAlbumMenu instanceof FloatingActionButton) {
                                ((FloatingActionButton) mAlbumMenu)
                                        .setColorNormal(mutedColor.getRgb());
                            }
                        } catch (final NullPointerException | IllegalStateException e) {
                            Log.e(TAG, "Error while applying generated album art palette colors",
                                    e);
                        }
                    }
                };

        mApp.getAsyncHelper().execAsync(new Runnable() {
            @Override
            public void run() {
                // Suppress this crash. It can happen (rarely) and it's not worth crashing over.
                if (bitmap != null && !bitmap.isRecycled()) {
                    final Palette.Builder builder = new Palette.Builder(bitmap);
                    builder.generate(paletteAsyncListener);
                }
            }
        });
    }

    @Override
    public void asyncUpdate() {
        try {
            if (getActivity() != null) {
                replaceItems(mApp.getMPD().getSongs(mAlbum));
                Collections.sort(mItems);
            }
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to async update.", e);
        }
    }

    @Override
    protected boolean forceEmptyView() {
{'fraction_non_alphanumeric': 0.08309598405012816, 'fraction_numerical': 0.0022785531187695814, 'mean_word_length': 2.5847371107708015, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '260699', 'n_tokens_mistral': 3920, 'n_tokens_neox': 3715, 'n_words': 878}