/******************************************************************************
* Copyright (C) 2012, 2013, 2014, 2015, 2016
* Younghyung Cho. <yhcting77@gmail.com>
* All rights reserved.
*
* This file is part of NetMBuddy
*
* This program is licensed under the FreeBSD license
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of the FreeBSD Project.
*****************************************************************************/
package free.yhc.netmbuddy;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import free.yhc.abaselib.AppEnv;
import free.yhc.baselib.Logger;
import free.yhc.netmbuddy.db.ColPlaylist;
import free.yhc.netmbuddy.db.DB;
import free.yhc.netmbuddy.core.UnexpectedExceptionHandler;
import free.yhc.netmbuddy.core.YTPlayer;
import free.yhc.netmbuddy.utils.Util;
import free.yhc.netmbuddy.utils.UxUtil;
public class MusicsActivity extends Activity implements
UnexpectedExceptionHandler.Evidence {
private static final boolean DBG = Logger.DBG_DEFAULT;
private static final Logger P = Logger.create(MusicsActivity.class, Logger.LOGLV_DEFAULT);
public static final String MAP_KEY_PLAYLIST_ID = "playlistid";
public static final String MAP_KEY_TITLE = "title";
public static final String MAP_KEY_KEYWORD = "keyword";
public static final String MAP_KEY_THUMBNAIL = "thumbnail";
private final DB mDb = DB.get();
private final YTPlayer mMp = YTPlayer.get();
private final MusicsAdapter.CheckStateListener mCheckListener
= new MusicsAdapter.CheckStateListener() {
@Override
public void
onStateChanged(int nrChecked, int pos, boolean checked) {
// do nothing.
}
};
private final OnPlayerUpdateDBListener mOnPlayerUpdateDbListener
= new OnPlayerUpdateDBListener();
private long mPlid = UxUtil.PLID_INVALID;
private ListView mListv = null;
private class OnPlayerUpdateDBListener implements YTPlayer.OnDBUpdatedListener {
@Override
public void
onDbUpdated(YTPlayer.DBUpdateType ty) {
switch (ty) {
case PLAYLIST:
if (null != getAdapter())
getAdapter().reloadCursorAsync();
}
// others are ignored.
}
}
private MusicsAdapter
getAdapter() {
return (MusicsAdapter)mListv.getAdapter();
}
private void
startVideos(YTPlayer.Video[] vs) {
if (!Util.isNetworkAvailable()) {
UxUtil.showTextToast(Err.IO_NET.getMessage());
return;
}
mMp.startVideos(vs);
}
private void
appendToPlayQ(YTPlayer.Video[] vids) {
mMp.appendToPlayQ(vids);
}
private void
addTo(final int[] poss, final boolean move) {
MusicsAdapter adpr = getAdapter();
final long[] mids = new long[poss.length];
for (int i = 0; i < mids.length; i++)
mids[i] = adpr.getItemId(poss[i]);
UxUtil.OnPostExecuteListener listener = new UxUtil.OnPostExecuteListener() {
@Override
public void
onPostExecute(Err result, Object user) {
if (Err.NO_ERR != result)
UxUtil.showTextToast(result.getMessage());
if (move)
getAdapter().reloadCursorAsync();
else
getAdapter().cleanChecked();
}
};
UxUtil.addVideosTo(this, null, listener, mPlid, mids, move);
}
private void
deleteMusics(final long[] mids) {
UxUtil.OnPostExecuteListener listener = new UxUtil.OnPostExecuteListener() {
@Override
public void
onPostExecute(Err result, Object tag) {
if (Err.NO_ERR == result)
getAdapter().reloadCursorAsync();
}
};
UxUtil.deleteVideos(this, null, listener, mPlid, mids);
}
private void
setToPlaylistThumbnail(@SuppressWarnings("unused") long mid,
int pos) {
P.bug(UxUtil.isUserPlaylist(mPlid));
byte[] data = getAdapter().getMusicThumbnail(pos);
mDb.updatePlaylist(mPlid,
new ColPlaylist[] { ColPlaylist.THUMBNAIL,
ColPlaylist.THUMBNAIL_YTVID },
new Object[] { data,
getAdapter().getMusicYtid(pos) });
UxUtil.setThumbnailImageView(((ImageView)findViewById(R.id.thumbnail)), data);
}
private void
onListItemClick(@SuppressWarnings("unused") View view,
int pos,
@SuppressWarnings("unused") long id) {
YTPlayer.Video vid = getAdapter().getYTPlayerVideo(pos);
startVideos(new YTPlayer.Video[] { vid });
}
private void
onToolPlay(@SuppressWarnings("unused") View anchor) {
MusicsAdapter adpr = getAdapter();
int[] poss = adpr.getCheckedMusicsSortedByTime();
if (0 == poss.length) {
UxUtil.showTextToast(R.string.msg_no_items_selected);
return;
}
YTPlayer.Video[] vs = new YTPlayer.Video[poss.length];
for (int i = 0; i < poss.length; i++)
vs[i] = adpr.getYTPlayerVideo(poss[i]);
startVideos(vs);
adpr.cleanChecked();
}
private void
onToolAppendPlayQ(@SuppressWarnings("unused") View anchor) {
MusicsAdapter adpr = getAdapter();
int[] poss = adpr.getCheckedMusicsSortedByTime();
if (0 == poss.length) {
UxUtil.showTextToast(R.string.msg_no_items_selected);
return;
}
YTPlayer.Video[] vids = new YTPlayer.Video[poss.length];
int j = 0;
for (int i : poss)
vids[j++] = adpr.getYTPlayerVideo(i);
appendToPlayQ(vids);
adpr.cleanChecked();
UxUtil.showTextToast(R.string.msg_appended_to_playq);
}
private void
onToolCopy(@SuppressWarnings("unused") View anchor) {
MusicsAdapter adpr = getAdapter();
int[] poss = adpr.getCheckedMusics();
if (0 == poss.length) {
UxUtil.showTextToast(R.string.msg_no_items_selected);
return;
}
addTo(poss, false);
}
private void
onToolMove(@SuppressWarnings("unused") View anchor) {
MusicsAdapter adpr = getAdapter();
int[] poss = adpr.getCheckedMusics();
if (0 == poss.length) {
UxUtil.showTextToast(R.string.msg_no_items_selected);
return;
}
addTo(poss, true);
}
private void
onToolDelete(@SuppressWarnings("unused") View anchor) {
MusicsAdapter adpr = getAdapter();
int[] poss = adpr.getCheckedMusics();
if (0 == poss.length) {
UxUtil.showTextToast(R.string.msg_no_items_selected);
return;
}
long[] mids = new long[poss.length];
for (int i = 0; i < poss.length; i++)
mids[i] = adpr.getItemId(poss[i]);
deleteMusics(mids);
}
private void
setupToolButtons() {
ImageView iv = (ImageView)findViewById(R.id.play);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void
onClick(View v) {
onToolPlay(v);
}
});
iv = (ImageView)findViewById(R.id.append_playq);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void
onClick(View v) {
onToolAppendPlayQ(v);
}
});
iv = (ImageView)findViewById(R.id.copy);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void
onClick(View v) {
onToolCopy(v);
}
});
iv = (ImageView)findViewById(R.id.move);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void
onClick(View v) {
onToolMove(v);
}
});
iv = (ImageView)findViewById(R.id.delete);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void
onClick(View v) {
onToolDelete(v);
}
});
}
private void
onContextMenuVolume(@SuppressWarnings("unused") final long id,
final int pos) {
mMp.changeVideoVolume(getAdapter().getMusicTitle(pos),
getAdapter().getMusicYtid(pos));
}
private void
onContextMenuAppendToPlayQ(@SuppressWarnings("unused") final long id,
final int pos) {
YTPlayer.Video vid = getAdapter().getYTPlayerVideo(pos);
appendToPlayQ(new YTPlayer.Video[] { vid });
}
private void
onContextMenuRename(final long id, final int pos) {
UxUtil.EditTextAction action = new UxUtil.EditTextAction() {
@Override
public void
prepare(Dialog dialog, EditText edit) { }
@Override
public void
onOk(Dialog dialog, EditText edit) {
mDb.updateVideoTitle(id, edit.getText().toString());
getAdapter().reloadCursorAsync();
}
};
UxUtil.buildOneLineEditTextDialog(this,
R.string.rename,
getAdapter().getMusicTitle(pos),
action)
.show();
}
private void
onContextMenuPlayVideo(@SuppressWarnings("unused") final long id,
final int pos) {
UxUtil.playAsVideo(this, getAdapter().getMusicYtid(pos));
}
private void
onContextMenuDetailInfo(final long id,
@SuppressWarnings("unused") final int pos) {
UxUtil.showVideoDetailInfo(this, id);
}
private void
onContextMenuBookmarks(@SuppressWarnings("unused") final long id,
final int pos) {
UxUtil.showBookmarkDialog(this,
getAdapter().getMusicYtid(pos),
getAdapter().getMusicTitle(pos));
}
private void
onContextMenuVideosOfThisChannel(@SuppressWarnings("unused") final long id,
final int pos) {
Intent i = new Intent(this, YTVideoSearchChannelActivity.class);
i.putExtra(YTSearchActivity.KEY_TEXT, getAdapter().getMusicChannelId(pos));
startActivity(i);
}
private void
onContextMenuSearchSimilarTitles(@SuppressWarnings("unused") final long id,
final int pos) {
UxUtil.showSimilarTitlesDialog(this, getAdapter().getMusicTitle(pos));
}
@Override
public String
dump(UnexpectedExceptionHandler.DumpLevel lvl) {
return this.getClass().getName();
}
// ========================================================================
//
// Overriding Activity Member Functions
//
// ========================================================================
@Override
public boolean
onContextItemSelected(MenuItem mItem) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)mItem.getMenuInfo();
switch (mItem.getItemId()) {
case R.id.add_to:
addTo(new int[] { info.position }, false);
return true;
case R.id.move_to:
addTo(new int[] { info.position }, true);
return true;
case R.id.volume:
onContextMenuVolume(info.id, info.position);
return true;
case R.id.append_to_playq:
onContextMenuAppendToPlayQ(info.id, info.position);
return true;
case R.id.plthumbnail:
setToPlaylistThumbnail(info.id, info.position);
return true;
case R.id.rename:
onContextMenuRename(info.id, info.position);
return true;
case R.id.play_video:
onContextMenuPlayVideo(info.id, info.position);
return true;
case R.id.delete:
deleteMusics(new long[] { info.id });
return true;
case R.id.detail_info:
onContextMenuDetailInfo(info.id, info.position);
return true;
case R.id.bookmarks:
onContextMenuBookmarks(info.id, info.position);
return true;
case R.id.videos_of_same_channel:
onContextMenuVideosOfThisChannel(info.id, info.position);
return true;
case R.id.search_similar_titles:
onContextMenuSearchSimilarTitles(info.id, info.position);
return true;
}
P.bug(false);
return false;
}
@Override
public void
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.musics_context, menu);
AdapterContextMenuInfo mInfo = (AdapterContextMenuInfo)menuInfo;
boolean visible = UxUtil.isUserPlaylist(mPlid);
menu.findItem(R.id.plthumbnail).setVisible(visible);
visible = Util.isValidValue(getAdapter().getMusicChannel(mInfo.position));
menu.findItem(R.id.videos_of_same_channel).setVisible(visible);
}
@Override
public void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UnexpectedExceptionHandler.get().registerModule(this);
setContentView(R.layout.musics);
String searchWord = null;
mPlid = getIntent().getLongExtra(MAP_KEY_PLAYLIST_ID, UxUtil.PLID_INVALID);
P.bug(UxUtil.PLID_INVALID != mPlid);
if (UxUtil.isUserPlaylist(mPlid)) {
String title = getIntent().getStringExtra(MAP_KEY_TITLE);
((TextView)findViewById(R.id.title)).setText(title);
byte[] imgdata = getIntent().getByteArrayExtra(MAP_KEY_THUMBNAIL);
UxUtil.setThumbnailImageView(((ImageView)findViewById(R.id.thumbnail)), imgdata);
} else if (UxUtil.PLID_RECENT_PLAYED == mPlid) {
((TextView)findViewById(R.id.title)).setText(R.string.recently_played);
((ImageView)findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_recently_played_up);
} else if (UxUtil.PLID_SEARCHED == mPlid) {
String word = getIntent().getStringExtra(MAP_KEY_KEYWORD);
searchWord = (null == word)? "": word;
String title = AppEnv.getAppContext().getResources().getText(R.string.keyword) + " : " + word;
((TextView)findViewById(R.id.title)).setText(title);
((ImageView)findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_search_list_up);
}
setupToolButtons();
mListv = (ListView)findViewById(R.id.list);
//mListv.setEmptyView(AUtil.inflateLayout(this, R.layout.ytsearch_empty_list));
registerForContextMenu(mListv);
mListv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void
onItemClick(AdapterView<?> parent, View view, int pos, long id) {
onListItemClick(view, pos, id);
}
});
MusicsAdapter adapter = new MusicsAdapter(this,
new MusicsAdapter.CursorArg(mPlid, searchWord),
mCheckListener);
mListv.setAdapter(adapter);
adapter.reloadCursorAsync();
}
@Override
protected void
onResume() {
super.onResume();
ViewGroup playerv = (ViewGroup)findViewById(R.id.player);
mMp.setController(this,
playerv,
(ViewGroup)findViewById(R.id.list_drawer),
null,
mMp.getVideoToolButton());
mMp.addOnDbUpdatedListener(mOnPlayerUpdateDbListener);
if (mMp.hasActiveVideo())
playerv.setVisibility(View.VISIBLE);
else
playerv.setVisibility(View.GONE);
}
@Override
protected void
onPause() {
mMp.removeOnDbUpdatedListener(mOnPlayerUpdateDbListener);
mMp.unsetController(this);
super.onPause();
}
@Override
protected void
onStop() {
super.onStop();
}
@Override
protected void
onDestroy() {
UnexpectedExceptionHandler.get().unregisterModule(this);
super.onDestroy();
}
@Override
protected void
onActivityResult(int requestCode, int resultCode, Intent data) {
if (Activity.RESULT_OK != resultCode)
return;
// TODO : NOT implemented yet
P.bug(false);
//noinspection StatementWithEmptyBody
switch (requestCode) {
}
}
@Override
public void
onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Do nothing!
}
@Override
public void
onBackPressed() {
super.onBackPressed();
}
}