/*
* Copyright (C) 2014 Fastboot Mobile, LLC.
*
* 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 3 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, see <http://www.gnu.org/licenses>.
*/
package com.fastbootmobile.encore.app.fragments;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import com.fastbootmobile.encore.api.chartlyrics.ChartLyricsClient;
import com.fastbootmobile.encore.api.common.RateLimitException;
import com.fastbootmobile.encore.app.MainActivity;
import com.fastbootmobile.encore.app.R;
import com.fastbootmobile.encore.framework.PlaybackProxy;
import com.fastbootmobile.encore.model.Artist;
import com.fastbootmobile.encore.model.Song;
import com.fastbootmobile.encore.providers.ProviderAggregator;
import com.fastbootmobile.encore.service.BasePlaybackCallback;
import java.io.IOException;
/**
* A fragment containing a simple view for lyrics.
*/
public class LyricsFragment extends Fragment {
private static final String TAG = "LyricsFragment";
private TextView mTvLyrics;
private ProgressBar mPbLoading;
private ChartLyricsClient.LyricsResponse mLyrics;
private Song mCurrentSong;
private Handler mHandler = new Handler();
private AsyncTask mLyricsTask;
private BasePlaybackCallback mPlaybackCallback = new BasePlaybackCallback() {
@Override
public void onSongStarted(boolean buffering, Song s) {
if (mCurrentSong == null || !s.equals(mCurrentSong)) {
mCurrentSong = s;
getLyrics(s);
}
}
};
public static LyricsFragment newInstance() {
return new LyricsFragment();
}
public LyricsFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ScrollView root = (ScrollView) inflater.inflate(R.layout.fragment_lyrics, container, false);
mTvLyrics = (TextView) root.findViewById(R.id.tvLyrics);
mPbLoading = (ProgressBar) root.findViewById(R.id.pbLoading);
updateLyrics();
return root;
}
/**
* {@inheritDoc}
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
MainActivity mainActivity = (MainActivity) activity;
mainActivity.onSectionAttached(MainActivity.SECTION_LYRICS);
}
@Override
public void onResume() {
super.onResume();
PlaybackProxy.addCallback(mPlaybackCallback);
updateLyrics();
}
@Override
public void onPause() {
super.onPause();
PlaybackProxy.removeCallback(mPlaybackCallback);
}
private void updateLyrics() {
mCurrentSong = PlaybackProxy.getCurrentTrack();
if (mCurrentSong != null && mCurrentSong.getArtist() != null) {
getLyrics(mCurrentSong);
} else if (mCurrentSong != null) {
mTvLyrics.setText(R.string.lyrics_no_artist_error);
mPbLoading.setVisibility(View.GONE);
} else {
mTvLyrics.setText(R.string.lyrics_placeholder);
mPbLoading.setVisibility(View.GONE);
}
}
private void getLyrics(final Song song) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mLyricsTask != null) {
mLyricsTask.cancel(true);
}
mLyricsTask = new GetLyricsTask().execute(song);
}
});
}
private class GetLyricsTask extends AsyncTask<Song, Void, ChartLyricsClient.LyricsResponse> {
private Song mSong;
@Override
protected void onPreExecute() {
mTvLyrics.setVisibility(View.GONE);
mPbLoading.setVisibility(View.VISIBLE);
}
@Override
protected ChartLyricsClient.LyricsResponse doInBackground(Song... params) {
mSong = params[0];
Artist artist = ProviderAggregator.getDefault().retrieveArtist(mSong.getArtist(), mSong.getProvider());
ChartLyricsClient.LyricsResponse lyrics = null;
if (artist != null) {
boolean resetByPeer = true;
while (resetByPeer && !isCancelled()) {
try {
lyrics = ChartLyricsClient.getSongLyrics(artist.getName(), mSong.getTitle());
resetByPeer = false;
} catch (IOException e) {
if (e.getMessage().contains("Connection reset by peer")) {
// ChartLyrics API resets connection to throttle fetching. Retry every few
// seconds until we get them.
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
break;
}
resetByPeer = true;
} else {
Log.e(TAG, "Cannot get lyrics", e);
resetByPeer = false;
}
} catch (RateLimitException e) {
Log.e(TAG, "Cannot get lyrics", e);
resetByPeer = false;
}
}
}
return lyrics;
}
@Override
protected void onPostExecute(ChartLyricsClient.LyricsResponse s) {
mLyrics = s;
if (mTvLyrics != null && mSong.equals(mCurrentSong) && !isCancelled()) {
mTvLyrics.setVisibility(View.VISIBLE);
mPbLoading.setVisibility(View.GONE);
if (s == null || s.lyrics == null) {
mTvLyrics.setText(R.string.lyrics_not_found);
} else {
StringBuilder result = new StringBuilder();
if (s.title != null) {
result.append(s.title);
result.append("\n");
}
if (s.artist != null) {
result.append(s.artist);
result.append("\n");
}
if (s.artist != null || s.title != null) {
// Add some padding if we had artist or title
result.append("\n\n");
}
if (s.lyrics != null) {
result.append(s.lyrics);
}
mTvLyrics.setText(result.toString());
}
}
}
}
}