/*
* RHome version 0.1
* http://rhome.r00li.com
* Copyright 2012, 2013 Andrej Rolih
* Licensed under GPLv3 - see LICENSE.txt
*
* Early development build. Not suitable for end-user.
*/
package com.r00li.rhome;
import java.util.ArrayList;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.type.TypeReference;
import org.xbmc.jsonrpc.Connection;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
/**
* Media player Class. Currently handles XBMC media player support.
* Itunes and other players should be added later. Based on the official XBMC remote for android.
* To be replaced with a custom system at a later date.
* @author Andrej Rolih
*
*/
public class MediaPlayer {
int type;
String name;
String username;
String password;
String adress;
int port;
boolean poll;
Thread poller;
Handler mHandler = new Handler();
RHomeActivity context;
mojManager manager;
MyAdapter ada;
XBMCMediaSelectedListenter poslusalec1;
ArrayList<String> dirLevel;
Connection c;
boolean playing;
boolean displayHold = false;
String playingTitle;
int playingPercentage;
Player activePlayer;
int playingVolume;
int time_p_seconds;
int time_p_hours;
int time_p_minutes;
int time_a_seconds;
int time_a_hours;
int time_a_minutes;
boolean paused;
TextView nowPlayingLabel;
MediaPlayer (int type, String name, String username, String password, String adress, int port, RHomeActivity context) {
this.type = type;
this.name = name;
this.username = username;
this.password = password;
this.adress = adress;
this.port = port;
this.context = context;
poslusalec1 = new XBMCMediaSelectedListenter();
dirLevel = new ArrayList<String>();
ada = new MyAdapter();
nowPlayingLabel = (TextView)this.context.nowPlayingLabel;
poslusalec1.onItemClick(null, null, 0, 0);
c = Connection.getInstance(this.adress, this.port);
c.setAuth(this.username, this.password);
c.setTimeout(0);
context.playerSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
boolean usermode = false;
int myprogress = 0;
public void onStopTrackingTouch(SeekBar seekBar) {
displayHold = false;
if (usermode)
sendCommand("seek", myprogress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
displayHold = true;
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
usermode = true;
myprogress = progress;
}
}
});
context.playerVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
boolean usermode = false;
int myprogress = 0;
public void onStopTrackingTouch(SeekBar seekBar) {
displayHold = false;
if (usermode)
sendCommand("volume", myprogress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
displayHold = true;
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
usermode = true;
myprogress = progress;
}
}
});
}
public void reconnect() {
c = Connection.getInstance(this.adress, this.port);
c.setAuth(this.username, this.password);
c.setTimeout(0);
}
void startPolling() {
if (type == 0) {
poll = true;
poller = new Thread(playerStatXBMC);
poller.start();
}
}
void stopPolling() {
poll = false;
}
void updateDisplay() {
if (displayHold)
return;
mHandler.post(new Runnable() {
public void run() {
if (playing) {
if (!nowPlayingLabel.getText().equals(playingTitle)) {
nowPlayingLabel.setText(playingTitle);
}
context.playerSeek.setProgress(playingPercentage);
context.playerVolume.setProgress(playingVolume);
String currentPlayingTime = String.format("%02d:%02d:%02d", time_p_hours, time_p_minutes, time_p_seconds);
String totalPlayingTime = String.format("%02d:%02d:%02d", time_a_hours, time_a_minutes, time_a_seconds);;
context.currentPlayingTime.setText(currentPlayingTime);
context.totalPlayingTime.setText(totalPlayingTime);
}
else {
nowPlayingLabel.setText("< Not active >");
context.playerSeek.setProgress(0);
context.playerVolume.setProgress(0);
context.currentPlayingTime.setText("");
context.totalPlayingTime.setText("");
}
}
});
}
void sendCommand(final String command, final int parameter) {
new Thread(new Runnable() {
public void run() {
try {
mojManager m = new mojManager();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode(); // will be of type ObjectNode
if (command.equals("pause")) {
((ObjectNode)rootNode).put("playerid", activePlayer.playerid);
JsonNode bla = c.getJson(m, "Player.PlayPause", rootNode);
}
else if (command.equals("stop")) {
((ObjectNode)rootNode).put("playerid", activePlayer.playerid);
JsonNode bla = c.getJson(m, "Player.Stop", rootNode);
}
else if (command.equals("seek")) {
((ObjectNode)rootNode).put("playerid", activePlayer.playerid);
((ObjectNode)rootNode).put("value", parameter);
JsonNode bla = c.getJson(m, "Player.Seek", rootNode);
}
else if (command.equals("volume")) {
((ObjectNode)rootNode).put("volume", parameter);
JsonNode bla = c.getJson(m, "Application.SetVolume", rootNode);
}
else if (command.equals("left")) {
JsonNode bla = c.getJson(m, "Input.Left", null);
}
else if (command.equals("right")) {
JsonNode bla = c.getJson(m, "Input.Right", null);
}
else if (command.equals("select")) {
JsonNode bla = c.getJson(m, "Input.Select", null);
}
else if (command.equals("back")) {
JsonNode bla = c.getJson(m, "Input.Back", null);
}
else if (command.equals("up")) {
JsonNode bla = c.getJson(m, "Input.Up", null);
}
else if (command.equals("down")) {
JsonNode bla = c.getJson(m, "Input.Down", null);
}
}
catch(Exception e) {
context.reportError();
//Log.w("MEDIA_ERROR", e.toString());
Log.w("MEDIA_ERROR", e.toString());
//e.printStackTrace();
}
}
}).start();
}
private Runnable playerStatXBMC = new Runnable() {
public void run() {
while(poll) {
mojManager m = new mojManager();
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)rootNode).put("media", "video");
JsonNode bla = c.getJson(m, "Player.GetActivePlayers", null);
ObjectMapper mp = new ObjectMapper();
final ArrayList<Player> neggg = mp.readValue(bla.traverse(), new TypeReference<ArrayList<Player>>() {});
Player pl = null;
for (Player p : neggg) {
if (p.type.equals("video") || p.type.equals("music")) {
pl = p;
}
}
final Player pp = pl;
activePlayer = pp;
if (pp != null) {
JsonNode requestNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)requestNode).put("playerid", pp.playerid);
((ObjectNode)requestNode).putArray("properties");
JsonNode nowPlay = c.getJson(m, "Player.GetItem", requestNode);
JsonNode nowPlayNode = nowPlay.get("item").get("label");
playing = true;
playingTitle = "► " + nowPlayNode.getTextValue();
requestNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)requestNode).put("playerid", pp.playerid);
((ObjectNode)requestNode).putArray("properties").add("percentage").add("time").add("totaltime").add("speed");
JsonNode nowPercentage = c.getJson(m, "Player.GetProperties", requestNode);
JsonNode percentageNode = nowPercentage.get("percentage");
playingPercentage = percentageNode.getIntValue();
//get the current playing time
time_p_seconds = nowPercentage.get("time").get("seconds").getIntValue();
time_p_hours = nowPercentage.get("time").get("hours").getIntValue();
time_p_minutes = nowPercentage.get("time").get("minutes").getIntValue();
//get the total time
time_a_seconds = nowPercentage.get("totaltime").get("seconds").getIntValue();
time_a_hours = nowPercentage.get("totaltime").get("hours").getIntValue();
time_a_minutes = nowPercentage.get("totaltime").get("minutes").getIntValue();
paused = (nowPercentage.get("speed").getIntValue() == 0) ? true:false;
if (paused) {
playingTitle = "║ " + nowPlayNode.getTextValue();
}
requestNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)requestNode).putArray("properties").add("volume");
JsonNode nowVolume = c.getJson(m, "Application.GetProperties", requestNode);
JsonNode volumeNode = nowVolume.get("volume");
playingVolume = volumeNode.getIntValue();
}
else {
playing = false;
}
updateDisplay();
}
catch(Exception e) {
Log.w("MEDIA_ERROR", e.toString());
//Log.w("BABABA", e.toString());
//e.printStackTrace();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
class XBMCMediaSelectedListenter implements OnItemClickListener {
public void onItemClick(AdapterView<?> a, View v,int position, long id)
{
File izbrano_temp;
if (a != null) {
izbrano_temp = (File) a.getItemAtPosition(position);
}
else {
if (!dirLevel.isEmpty())
dirLevel.remove(dirLevel.size()-1);
if (!dirLevel.isEmpty())
izbrano_temp = new File(dirLevel.get(dirLevel.size()-1), "back1");
else
izbrano_temp = new File("", "top");
}
final File izbrano = izbrano_temp;
if (izbrano.getFiletype().equals("file")) {
new Thread(new Runnable() {
public void run() {
mojManager m = new mojManager();
ObjectMapper mapper = new ObjectMapper();
JsonNode fileNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)fileNode).put("file", izbrano.file);
ArrayNode request = mapper.createArrayNode();
request.add(fileNode);
JsonNode nowPlay = c.getJson(m, "Player.Open", request);
}
}).start();
}
else if (izbrano.getFiletype().equals("directory") || izbrano.getFiletype().equals("") || izbrano.getFiletype().equals("back1")) {
new Thread(new Runnable() {
public void run() {
mojManager m = new mojManager();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)rootNode).put("directory", izbrano.file);
try {
JsonNode bla = c.getJson(m, "Files.GetDirectory", rootNode);
ObjectMapper mp = new ObjectMapper();
JsonNode list = bla.get("files");
final ArrayList<File> neggg = mp.readValue(list.traverse(), new TypeReference<ArrayList<File>>() {});
if (!izbrano.getFiletype().equals("back1"))
dirLevel.add(izbrano.file);
mHandler.post(new Runnable() {
public void run() {
ada.setItems(neggg);
ada.notifyDataSetChanged();
}});
}
catch(Exception e) {
Log.w("MEDIA_ERROR", e.toString());
//Log.w("BABABA", e.toString());
//e.printStackTrace();
}
}
}).start();
}
else if (izbrano.getFiletype().equals("top")) {
new Thread(new Runnable() {
public void run() {
mojManager m = new mojManager();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode(); // will be of type ObjectNode
((ObjectNode)rootNode).put("media", "video");
try {
JsonNode bla = c.getJson(m, "Files.GetSources", rootNode);
JsonParser a = bla.traverse();
ObjectMapper mp = new ObjectMapper();
JsonNode list = bla.get("sources");
final ArrayList<File> neggg = mp.readValue(list.traverse(), new TypeReference<ArrayList<File>>() {});
mHandler.post(new Runnable() {
public void run() {
ada.setItems(neggg);
ada.notifyDataSetChanged();
}});
}
catch(Exception e) {
Log.w("MEDIA_ERROR", e.toString());
//Log.w("BABABA", e.toString());
//e.printStackTrace();
}
}
}).start();
}
}
}
class MyAdapter extends BaseAdapter {
//Context context;
ArrayList<File> itemsArray;
MyAdapter(){
//context = c;
itemsArray = new ArrayList<File>();
}
public void setItems(ArrayList<File> items) {
if (items != null)
itemsArray = items;
}
public int getCount() {
// TODO Auto-generated method stub
return itemsArray.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return itemsArray.get(position);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View rowView = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.row, null);
TextView listTextView = (TextView)rowView.findViewById(R.id.itemtext);
listTextView.setText(itemsArray.get(position).getLabel());
if (itemsArray.get(position).getFiletype().equals("file")) {
TextView ch = (TextView)rowView.findViewById(R.id.movie);
ch.setText("X");
}
return rowView;
}
}
}