package com.sound.ampache.fragments; /* Copyright (c) 2008 Kevin James Purdy <purdyk@onid.orst.edu> * Copyright (c) 2010 Jacob Alexander < haata@users.sf.net > * Copyright (c) 2010 Kristopher Heijari < iix.ftw@gmail.com > * * +------------------------------------------------------------------------+ * | 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., 59 Temple Place - Suite 330, | * | Boston, MA 02111-1307, USA. | * +------------------------------------------------------------------------+ */ import android.app.Fragment; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.sound.ampache.GlobalMediaPlayerControl; import com.sound.ampache.R; import com.sound.ampache.amdroid; import com.sound.ampache.objects.Media; import com.sound.ampache.objects.Song; import com.sound.ampache.service.AbstractPlayerServiceStatusListener; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; public final class PlaylistFragment extends Fragment implements OnItemClickListener, GlobalMediaPlayerControl.PlayingIndexListener, GlobalMediaPlayerControl.PlaylistCurrentListener { private View empty; private ListView lv; private ImageView artView; private PlaylistAdapter pla; private Boolean albumArtEnabled = false; private PlaybackListener playbackListener = new PlaybackListener(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.playlist_layout, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); empty = view.findViewById(android.R.id.empty); lv = (ListView) view.findViewById(R.id.list); lv.setOnItemClickListener(this); pla = new PlaylistAdapter(getActivity()); lv.setAdapter(pla); // register our adapter to be called when a change to the currentPlaylist ocurrs amdroid.playbackControl.setPlayingIndexListener(this); //register ourselves to receive callbacks when playing index changes occurr amdroid.playbackControl.setPlaylistCurrentListener(this); // Setup Album Art View TODO artView = (ImageView) view.findViewById(R.id.picview); // Load Album Art on Entry, currently SLOOOOOOW so TODO //if ( amdroid.playbackControl.getPlaylistCurrent().size() > 0 ) // loadAlbumArt(); // Center the playlist at the current song centerList(0); } @Override public void onStart() { super.onStart(); amdroid.playbackControl.registerServiceStatusListener(playbackListener); } @Override public void onStop() { super.onStop(); amdroid.playbackControl.unregisterServiceStatusListener(playbackListener); } /*@Override public boolean onPrepareOptionsMenu(Menu menu) { menu.clear(); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.playlist_menu, menu); return true; }*/ /*@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.pl_clear: if (amdroid.playbackControl.isPlaying()) amdroid.playbackControl.stop(); amdroid.playbackControl.setPlayingIndex(0); pla.clearItems(); break; case R.id.pl_save: try { FileOutputStream pout = openFileOutput("playlist", 0); ObjectOutputStream pos = new ObjectOutputStream(pout); pos.writeObject(amdroid.playbackControl.getPlaylistCurrent()); pout.close(); } catch (Exception poo) { Toast.makeText(this, "Error: " + poo.toString(), Toast.LENGTH_LONG).show(); } break; case R.id.pl_load: if (amdroid.playbackControl.isPlaying()) amdroid.playbackControl.stop(); amdroid.playbackControl.setPlayingIndex(0); //mc.setEnabled(false); try { FileInputStream pin = openFileInput("playlist"); ObjectInputStream poin = new ObjectInputStream(pin); amdroid.playbackControl.addAllPlaylistCurrent( (ArrayList<Media>) poin.readObject() ); pin.close(); } catch (Exception poo) { Toast.makeText(this, "Error: " + poo.toString(), Toast.LENGTH_LONG).show(); } pla.refresh(); break; case R.id.pl_albumart: if (albumArtEnabled) { albumArtEnabled = false; artView.setVisibility(View.GONE); } else { artView.setVisibility(View.VISIBLE); albumArtEnabled = true; loadAlbumArt(); } break; } return true; }*/ private void loadAlbumArt() { if (amdroid.playbackControl.getPlaylistCurrent().size() <= 0 || !albumArtEnabled) { artView.setVisibility(View.GONE); return; } int i = amdroid.playbackControl.getPlayingIndex(); if (i >= amdroid.playbackControl.getPlaylistCurrent().size()) return; Song chosen = (Song) amdroid.playbackControl.getPlaylistCurrent().get(amdroid.playbackControl.getPlayingIndex()); Log.i("Amdroid", "Art URL - " + chosen.art); Log.i("Amdroid", "Art URL (C) - " + chosen.liveArt("#TOKEN#")); try { URL artUrl = new URL(chosen.liveArt("#TOKEN#")); Object artContent = artUrl.getContent(); Drawable albumArt = Drawable.createFromStream((InputStream) artContent, "src"); artView.setImageDrawable(albumArt); if (artView.getDrawable() != null) artView.setVisibility(View.VISIBLE); /* Something needs to happen here to clear the image view, too lazy atm */ else { artView.setVisibility(View.GONE); } } catch (MalformedURLException e) { Log.i("Amdroid", "Album Art URL sucks! Try something else."); } catch (IOException e) { Log.i("Amdroid", "Teh interwebs died..."); } } /* These functions help with displaying the |> icon next to the currently playing song */ private void turnOffPlayingView() { /* TODO we should probably keep track of which song we've displayed a playing icon for. * Looping through all items in the listview will be unneffective for large lists */ for (int i = 0; i < lv.getChildCount(); i++) { View holder = lv.getChildAt(i); if (holder != null) { ImageView img = (ImageView) holder.findViewById(R.id.art); img.setVisibility(View.INVISIBLE); } } } private void turnOnPlayingView() { if (amdroid.playbackControl.getPlayingIndex() >= lv.getFirstVisiblePosition() && amdroid.playbackControl.getPlayingIndex() <= lv.getLastVisiblePosition()) { View holder = lv.getChildAt(amdroid.playbackControl.getPlayingIndex() - lv.getFirstVisiblePosition()); if (holder != null) { ImageView img = (ImageView) holder.findViewById(R.id.art); img.setVisibility(View.VISIBLE); } } } @Override public void onItemClick(AdapterView l, View v, int position, long id) { if (amdroid.playbackControl.prepared) { amdroid.playbackControl.setPlayingIndex(position); amdroid.playbackControl.play(); } } private void centerList(int adjust) { int playlistIndex = amdroid.playbackControl.getPlayingIndex(); lv.setSelection(playlistIndex + adjust); refreshEmptyView(); } private class PlaylistAdapter extends BaseAdapter { private LayoutInflater mInflater; public PlaylistAdapter(Context context) { mInflater = LayoutInflater.from(context); } public int getCount() { return amdroid.playbackControl.getPlaylistCurrent().size(); } public Object getItem(int position) { return amdroid.playbackControl.getPlaylistCurrent().get(position); } public long getItemId(int position) { return position; } public void refresh() { notifyDataSetChanged(); } public void clearItems() { amdroid.playbackControl.clearPlaylistCurrent(); notifyDataSetChanged(); } @Override public boolean isEmpty() { return getCount() <= 0; } public View getView(int position, View convertView, ViewGroup parent) { plI holder; Media cur = amdroid.playbackControl.getPlaylistCurrent().get(position); /* we don't reuse */ if (convertView == null) { convertView = mInflater.inflate(R.layout.playlist_item, null); holder = new plI(); holder.title = (TextView) convertView.findViewById(R.id.title); holder.other = (TextView) convertView.findViewById(R.id.other); holder.art = (ImageView) convertView.findViewById(R.id.art); convertView.setTag(holder); } else { holder = (plI) convertView.getTag(); } holder.title.setText(cur.name); holder.other.setText(cur.extraString()); if (amdroid.playbackControl.getPlayingIndex() == position) { holder.art.setVisibility(View.VISIBLE); } else { holder.art.setVisibility(View.INVISIBLE); } return convertView; } } static class plI { TextView title; TextView other; ImageView art; } /*public boolean onKeyDown(int keyCode, KeyEvent event) { if (android.os.Build.VERSION.SDK_INT < 5 && keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { onBackPressed(); return true; } return super.onKeyDown(keyCode, event); }*/ @Override public void onPlayingIndexChange() { turnOffPlayingView(); centerList(-1); turnOnPlayingView(); loadAlbumArt(); } private void refreshEmptyView() { if (pla.isEmpty()) { empty.setVisibility(View.VISIBLE); } else { empty.setVisibility(View.GONE); } } @Override public void onPlaylistCurrentChange() { pla.notifyDataSetChanged(); refreshEmptyView(); } private class PlaybackListener extends AbstractPlayerServiceStatusListener { @Override public void onNewMedia() { updatePlaylist(); } @Override public void onPlaylistIndexChanged(int index) { updatePlaylist(); } @Override public void onPlaylistChanged(int size) { updatePlaylist(); } private void updatePlaylist() { onPlayingIndexChange(); } } }