Added precaching of next track when playing track is almost finished.

This commit is contained in:
Daniel Önnerby 2009-08-09 20:57:19 +00:00
parent a0c37bca1f
commit 32baa51f0d
8 changed files with 154 additions and 37 deletions

View File

@ -13,6 +13,7 @@
<TextView android:id="@+id/TextView01" android:layout_height="wrap_content" android:text="Browse by:" android:layout_width="fill_parent" android:background="@color/headlineColor" android:textSize="16sp" android:padding="4sp"></TextView>
<Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:textSize="22sp" android:text="Genre" android:id="@+id/GenresButton"></Button>
<Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:textSize="22sp" android:id="@+id/ArtistsButton" android:text="Artist"></Button>
</LinearLayout>
<TextView android:id="@+id/StatusView" android:text="Status: -" android:layout_width="fill_parent" android:background="@color/headlineColor" android:textSize="16sp" android:padding="4sp" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="0.1"></TextView>

View File

@ -1,2 +1,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:title="@string/menu_settings" android:id="@+id/context_settings" android:enabled="true" android:visible="true"></item>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/menu_browse" android:id="@+id/context_browse" android:enabled="true" android:visible="true"></item>
<item android:title="@string/menu_controls" android:id="@+id/context_controls" android:enabled="true" android:visible="true"></item>
<item android:title="@string/menu_settings" android:id="@+id/context_settings" android:enabled="true" android:visible="true"></item>
</menu>

View File

@ -16,4 +16,6 @@
<string name="queryport">10543</string>
<string name="httpport">10544</string>
<color name="headlineColor">#333333</color>
<string name="menu_controls">Player controls</string>
<string name="menu_browse">Browse</string>
</resources>

View File

@ -14,6 +14,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@ -219,4 +222,26 @@ public class CategoryList extends ListActivity implements OnQueryResultListener
startService(new Intent(this, org.musikcube.Service.class));
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.default_menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
//Log.i("MC2.onContextItemSelected","item "+item.getItemId()+" "+R.id.context_settings);
switch (item.getItemId()) {
case R.id.context_settings:
startActivity(new Intent(this, org.musikcube.Preferences.class));
return true;
case R.id.context_browse:
startActivity(new Intent(this, org.musikcube.main.class));
return true;
case R.id.context_controls:
startActivity(new Intent(this, org.musikcube.PlayerControl.class));
return true;
default:
return super.onContextItemSelected(item);
}
}
}

View File

@ -15,6 +15,9 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
@ -219,4 +222,29 @@ public class PlayerControl extends Activity implements OnTrackUpdateListener, On
seconds+=0.1; updatecount();
} }, 100, 100);
*/
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.default_menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
//Log.i("MC2.onContextItemSelected","item "+item.getItemId()+" "+R.id.context_settings);
switch (item.getItemId()) {
case R.id.context_settings:
startActivity(new Intent(this, org.musikcube.Preferences.class));
return true;
case R.id.context_browse:
startActivity(new Intent(this, org.musikcube.main.class));
return true;
case R.id.context_controls:
startActivity(new Intent(this, org.musikcube.PlayerControl.class));
return true;
default:
return super.onContextItemSelected(item);
}
}
}

View File

@ -16,6 +16,7 @@ public class Player implements TrackPlayer.OnTrackStatusListener{
private ArrayList<TrackPlayer> playingTracks = new ArrayList<TrackPlayer>();
private TrackPlayer currentPlayer;
private TrackPlayer nextPlayer;
public android.app.Service service;
@ -52,28 +53,56 @@ public class Player implements TrackPlayer.OnTrackStatusListener{
this.Play();
}
private TrackPlayer PrepareTrack(int position){
synchronized(this.lock){
if(this.nowPlaying.size()>position && position>=0){
int trackId = this.nowPlaying.get(position);
String url = "http://"+this.library.host+":"+this.library.httpPort+"/track/?track_id="+trackId+"&auth_key="+this.library.authorization;
TrackPlayer player = new TrackPlayer(url,trackId);
return player;
}
}
return null;
}
public void Play(){
this.Startup();
this.StopAllTracks();
TrackPlayer newPlayer = null;
synchronized(this.lock){
String url = "http://"+this.library.host+":"+this.library.httpPort+"/track/?track_id="+this.nowPlaying.get(this.position)+"&auth_key="+this.library.authorization;
TrackPlayer player = new TrackPlayer(url,true);
player.listener = this;
this.playingTracks.add(player);
this.currentPlayer = player;
if(this.listener!=null){
this.listener.OnTrackUpdate();
this.listener.OnTrackBufferUpdate(0);
this.listener.OnTrackPositionUpdate(0);
if(this.nowPlaying.size()>position && position>=0){
int trackId = this.nowPlaying.get(position);
if(this.nextPlayer!=null){
if(this.nextPlayer.trackId==trackId){
newPlayer = this.nextPlayer;
this.nextPlayer = null;
}else{
// Something wrong here, not the prepared track
this.nextPlayer.Stop();
this.nextPlayer = null;
}
}
if(newPlayer==null){
newPlayer = this.PrepareTrack(this.position);
}
this.playingTracks.add(newPlayer);
this.currentPlayer = newPlayer;
newPlayer.listener = this;
newPlayer.Play();
if(this.listener!=null){
this.listener.OnTrackUpdate();
this.listener.OnTrackBufferUpdate(0);
this.listener.OnTrackPositionUpdate(0);
}
}
}
}
///////////////////////////////
// Inteface for updated track
// Interface for updated track
public interface OnTrackUpdateListener{
public void OnTrackUpdate();
public void OnTrackBufferUpdate(int percent);
@ -147,10 +176,12 @@ public class Player implements TrackPlayer.OnTrackStatusListener{
}
public void OnTrackStatusUpdate(TrackPlayer trackPlayer,int status) {
// this.Next();
Intent intent = new Intent(this.service, org.musikcube.Service.class);
if(status==TrackPlayer.STATUS_EXIT){
this.Next();
}
/* Intent intent = new Intent(this.service, org.musikcube.Service.class);
intent.putExtra("org.musikcube.Service.action", "next");
this.service.startService(intent);
this.service.startService(intent);*/
}
public int GetCurrentTrackId(){
@ -183,4 +214,12 @@ public class Player implements TrackPlayer.OnTrackStatusListener{
return 0;
}
public void OnTrackAlmostDone(TrackPlayer trackPlayer) {
synchronized(this.lock){
if(this.nextPlayer==null){
this.nextPlayer = this.PrepareTrack(this.position+1);
}
}
}
}

View File

@ -4,18 +4,20 @@ import android.media.MediaPlayer;
public class TrackPlayer implements Runnable, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener,MediaPlayer.OnBufferingUpdateListener {
public int trackId = 0;
private Thread thread;
private String url;
private java.lang.Object lock = new java.lang.Object();
private MediaPlayer mediaPlayer;
private int buffer = 0;
private boolean almostDoneSend = false;
private int status = 1;
private static final int STATUS_PREPARED = 1;
private static final int STATUS_PLAYING = 2;
private static final int STATUS_PAUSE = 3;
private static final int STATUS_EXIT = 10;
public static final int STATUS_PREPARED = 1;
public static final int STATUS_PLAYING = 2;
public static final int STATUS_PAUSE = 3;
public static final int STATUS_EXIT = 10;
public void run() {
synchronized(this.lock){
@ -44,37 +46,50 @@ public class TrackPlayer implements Runnable, MediaPlayer.OnCompletionListener,
this.mediaPlayer.start();
synchronized(this.lock){
while(this.status==STATUS_PLAYING)
this.lock.wait();
while(this.status==STATUS_PLAYING){
if(!this.almostDoneSend){
int duration = this.mediaPlayer.getDuration();
int position = this.mediaPlayer.getCurrentPosition();
if(duration>0 && position+10000>duration){
// The track is almost done
this.almostDoneSend = true;
if(this.listener!=null){
this.listener.OnTrackAlmostDone(this);
}
}
}
this.lock.wait(3000);
}
}
this.mediaPlayer.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
synchronized(this.lock){
this.status = STATUS_EXIT;
}
}
synchronized(this.lock){
this.status = STATUS_EXIT;
}
this.CallListener();
}
public TrackPlayer(String url){
public TrackPlayer(String url,int trackId){
this.trackId = trackId;
this.url = url;
this.thread = new Thread(this);
this.thread.start();
}
public TrackPlayer(String url,boolean start){
/* public TrackPlayer(String url,boolean start){
this.url = url;
if(start==true){
this.status = STATUS_PLAYING;
}
this.thread = new Thread(this);
this.thread.start();
}
}*/
private void Exit(){
synchronized(this.lock){
@ -101,15 +116,13 @@ public class TrackPlayer implements Runnable, MediaPlayer.OnCompletionListener,
}
}
public boolean Play(){
public void Play(){
synchronized(this.lock){
if(this.status==STATUS_PLAYING || this.status==STATUS_PREPARED){
this.status = STATUS_PLAYING;
this.lock.notifyAll();
return true;
}
this.lock.notifyAll();
}
return false;
}
private void CallListener(){
@ -126,6 +139,7 @@ public class TrackPlayer implements Runnable, MediaPlayer.OnCompletionListener,
public interface OnTrackStatusListener{
public void OnTrackStatusUpdate(TrackPlayer trackPlayer,int status);
public void OnTrackAlmostDone(TrackPlayer trackPlayer);
}
public OnTrackStatusListener listener = null;

View File

@ -68,10 +68,15 @@ public class main extends Activity implements OnLibraryStatusListener {
public boolean onOptionsItemSelected(MenuItem item) {
//Log.i("MC2.onContextItemSelected","item "+item.getItemId()+" "+R.id.context_settings);
switch (item.getItemId()) {
case R.id.context_settings:
Intent intent = new Intent(main.this, Preferences.class);
startActivity(intent);
return true;
case R.id.context_settings:
startActivity(new Intent(this, org.musikcube.Preferences.class));
return true;
case R.id.context_browse:
startActivity(new Intent(this, org.musikcube.main.class));
return true;
case R.id.context_controls:
startActivity(new Intent(this, org.musikcube.PlayerControl.class));
return true;
default:
return super.onContextItemSelected(item);
}