//
// anyRemote android client
// a bluetooth/wi-fi remote control for Linux.
//
// Copyright (C) 2011-2016 Mikhail Fedotov <anyremote@mail.ru>
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package anyremote.client.android;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.TimerTask;
import java.util.Vector;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
import anyremote.client.android.util.Address;
import anyremote.client.android.util.InfoMessage;
import anyremote.client.android.util.ListItem;
import anyremote.client.android.util.ProtocolMessage;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class Dispatcher {
static final int CMD_NO = 0; // commands
static final int CMD_BG = 1;
static final int CMD_CAPTION = 2;
static final int CMD_EFIELD = 3;
static final int CMD_FG = 4;
static final int CMD_FMAN = 5;
static final int CMD_FONT = 6;
static final int CMD_FSCREEN = 7;
static final int CMD_ICONLIST = 8;
static final int CMD_ICONS = 9;
static final int CMD_HINTS = 10;
static final int CMD_LIST = 11;
static final int CMD_MENU = 12;
static final int CMD_PARAM = 13;
static final int CMD_REPAINT = 14;
static final int CMD_LAYOUT = 15;
static final int CMD_STATUS = 16;
static final int CMD_TEXT = 17;
static final int CMD_TITLE = 18;
static final int CMD_IMAGE = 19;
static final int CMD_VIBRATE = 20;
static final int CMD_VOLUME = 21;
static final int CMD_COVER = 22;
static final int CMD_POPUP = 23;
static final int CMD_GETSCRSIZE = 51;
static final int CMD_GETPLTF = 52;
static final int CMD_GETIMG = 53;
static final int CMD_GETCVRSIZE = 54;
static final int CMD_GETVER = 55;
static final int CMD_GETCURSOR = 56;
static final int CMD_GETPASS = 57;
static final int CMD_GETPING = 58;
static final int CMD_GETICSIZE = 59;
static final int CMD_GETPADDING = 60;
static final int CMD_CLOSECONN = 101;
//static final int CMD_EXIT = 102;
static final int CMD_EDIT_FORM_IP = 103; // Internal pseudo-commands
static final int CMD_EDIT_FORM_BT = 104;
static final int CMD_EDIT_FORM_ADDR = 105;
static final int CMD_SEARCH_DIALOG = 106;
static final int CMD_NEW_ADDR_DIALOG = 107;
static final int CMD_SENSOR_DIALOG = 108;
static final int CMD_LIST_UPDATE = 110;
static final int CMD_CLOSE = 120;
static final int SIZE_SMALL = 12;
static final int SIZE_MEDIUM = 22;
static final int SIZE_LARGE = 36;
static final int MAX_ATTEMPTS = 100;
static final int NOTUPDATE_NOTSWITCH = 1;
static final int NOTUPDATE_SWITCH = 2;
static final int UPDATE_SWITCH = 3;
static final int UPDATE_NOTSWITCH = 4;
static final String M_SENSOR = "_mouse_sensor_";
public static class ArHandler {
public ArHandler(int a,Handler h) {
actId = a;
hdl = h;
}
public int actId = anyRemote.NO_FORM;
public Handler hdl = null;
}
public static class QueueMessage {
public int activity;
public int id;
public int stage;
public int attemptsToSend;
}
private ArrayList<Handler> handlers;
ArrayList<ArHandler> actHandlers = new ArrayList<ArHandler>();
ArrayList<QueueMessage> msgQueue = new ArrayList<QueueMessage>();
ArrayList<String> autoUploadedI = new ArrayList<String>();
ArrayList<String> autoUploadedC = new ArrayList<String>();
Connection connection = null;
anyRemote context = null;
boolean autoPass = false;
String currentConnection = "";
String currentConnName = "";
String currentConnPass = "";
boolean fullscreen = false;
// Control Screen stuff
Vector<String> cfMenu = new Vector<String>();
int cfSkin;
boolean cfUseJoystick;
String cfTitle;
String cfStatus;
String cfCaption;
String [] cfIcons;
String [] cfHints;
String cfUpEvent;
String cfDownEvent;
int cfInitFocus;
int cfFrgr;
int cfBkgr;
Bitmap cfCover;
String cfNamedCover;
float cfFSize;
Typeface cfTFace;
String cfVolume;
int cfPadding;
int cfIconSize;
int cfIconSizeOverride;
// List Screen stuff
String listTitle;
int listSelectPos = -1;
Vector<String> listMenu = new Vector<String>();
ArrayList<ListItem> listContent = null;
boolean listCustomBackColor = false;
boolean listCustomTextColor = false;
int listText;
int listBkgr;
float listFSize;
String listIcon;
StringBuilder listBufferedItem;
// Text Screen stuff
String textTitle;
Vector<String> textMenu = new Vector<String>();
StringBuilder textContent;
int textFrgr;
int textBkgr;
float textFSize;
Typeface textTFace;
// Image Screen stuff
Bitmap imScreen;
Vector<String> winMenu = new Vector<String>();
// Mouse Screen stuff
//Vector<String> mouseMenu = new Vector<String>();
private boolean useGyroscope = true;
// Keyboard Screen stuff
//Vector<String> keyboardMenu = new Vector<String>();
// Web Screen stuff
String webUrl;
//Vector<String> webMenu = new Vector<String>();
// telephony handler
PhoneManager phoneManager;
// Popup stuff
boolean popupState = false;
StringBuilder popupMsg = new StringBuilder(16);
// Edit Field stuff
String efCaption = "";
String efLabel = "";
String efValue = "";
int efId;
boolean connectBT = false;
int keepaliveTimeout = -1;
int keepaliveCounter = 0;
public Dispatcher(anyRemote ctx) {
log("Dispatcher::Dispatcher");
handlers = new ArrayList<Handler>();
context = ctx;
listContent = new ArrayList<ListItem>();
cfIcons = new String[ControlScreen.NUM_ICONS];
cfHints = new String[ControlScreen.NUM_ICONS];
listBufferedItem = new StringBuilder();
textContent = new StringBuilder();
setDefValues();
TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
phoneManager = new PhoneManager(ctx, this);
telephonyManager.listen(phoneManager, PhoneStateListener.LISTEN_CALL_STATE);
}
public void setDefValues() {
for (int i=0;i<ControlScreen.NUM_ICONS;i++) {
cfIcons[i] = "none";
}
for (int i=0;i<ControlScreen.NUM_ICONS;i++) {
cfHints[i] = "";
}
cfSkin = ControlScreen.SK_DEFAULT;
cfUpEvent = "UP";
cfDownEvent = "DOWN";
cfInitFocus = 4; // index of '5' button
cfFrgr = Color.parseColor("#FFFFFF");
cfBkgr = Color.parseColor("#000000");
cfTitle = "";
cfStatus = "";
cfCaption = "";
cfCover = null;
cfNamedCover = "";
cfIconSizeOverride = -1;
cfPadding = 0;
cfIconSize = -1;
cfFSize = SIZE_MEDIUM;
cfTFace = Typeface.defaultFromStyle(Typeface.NORMAL);
cfMenu.clear();
menuAddDefault(anyRemote.CONTROL_FORM);
listTitle = "";
listIcon = "";
listSelectPos = -1;
listCustomBackColor = false;
listCustomTextColor = false;
listContent.clear();
listFSize = -1;
listMenu.clear();
menuAddDefault(anyRemote.LIST_FORM);
listBufferedItem.delete(0, listBufferedItem.length());
textFrgr = Color.parseColor("#FFFFFF");
textBkgr = Color.parseColor("#000000");
textContent.delete(0, textContent.length());
textFSize = SIZE_MEDIUM;
textTFace = Typeface.defaultFromStyle(Typeface.NORMAL);
textMenu.clear();
menuAddDefault(anyRemote.TEXT_FORM);
imScreen = null;
winMenu.clear();
menuAddDefault(anyRemote.WMAN_FORM);
//mouseMenu.clear();
//menuAddDefault(anyRemote.MOUSE_FORM);
//keyboardMenu.clear();
//menuAddDefault(anyRemote.KEYBOARD_FORM);
//webMenu.clear();
//menuAddDefault(anyRemote.WEB_FORM);
autoPass = false;
}
public void doConnect(String name, String host, String pass) {
log("doConnect " + (host!=null?host:"NULL")+" P=>"+pass+"<");
if (connection != null && !connection.isClosed()) {
log("doConnect already connected to " + currentConnection);
anyRemote.sendGlobal(anyRemote.CONNECTED, "");
return;
}
if (host != null && host.length() > 0) {
currentConnName = name;
currentConnPass = pass;
if (host.startsWith("socket://")) {
currentConnection = host;
connectWifi(host);
return;
} else if (host.startsWith("btspp://")) {
currentConnection = host;
connectBluetooth(host);
return;
}
}
log("doConnect: cannot establish");
anyRemote.sendGlobal(anyRemote.DISCONNECTED, "");
}
/**
* connects to a wifi remote anyRemote server
* @param hostname the host to connect to
* @param port the port to connect to
* @param clientInfo client info describing this client
*/
public void connectWifi(String host){
log("connectWifi");
connectBT = false;
MainLoop.schedule(new ConnectTask(ConnectTask.WIFI, host, this));
}
/**
* connects to a bluetooth remote anyRemote server
* @param hostname the host to connect to
* @param clientInfo client info describing this client
*/
public void connectBluetooth(String host){
log("connectBluetooth");
connectBT = true;
MainLoop.schedule(new ConnectTask(ConnectTask.BLUETOOTH, host, this));
}
/**
* disconnects from the server
* does nothing if not connected
*/
public void disconnect(boolean full) {
log("disconnect "+full);
boolean isConn = (connection != null && !connection.isClosed());
disconnected(full);
if (isConn) {
if (full) {
anyRemote.sendGlobal(anyRemote.DISCONNECTED, "");
} else {
anyRemote.sendGlobal(anyRemote.LOSTFOCUS, "");
}
} else{
log("disconnect: alredy disconnected");
}
}
public void disconnected(boolean full) {
if (connection != null) {
connection.close();
connection = null;
autoPass = false;
}
synchronized (msgQueue) {
msgQueue.clear();
}
if (full) {
currentConnection = "";
currentConnName = "";
}
setDefValues();
}
public void pauseConnection(){
log("pauseConnection");
disconnect(false);
}
public void connected(Connection conn) {
log("connected");
// check BT connection
if (connectBT) {
try {
ComponentName comp = new ComponentName(context, this.getClass());
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(), 0);
queueCommand("Version(,"+pinfo.versionName);
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
queueCommand("Version(,unknown)");
}
}
connection = conn;
}
public static String cmdStr(int cmd) {
switch (cmd) {
case CMD_NO: return "CMD_NO";
case CMD_BG : return "Set(bg)";
case CMD_CAPTION : return "Set(caption)";
case CMD_EFIELD: return "Set(editfield)";
case CMD_FG: return "Set(fg)";
case CMD_FMAN: return "Set(filemanager)";
case CMD_FONT: return "Set(font)";
case CMD_FSCREEN: return "Set(fullscreen)";
case CMD_ICONLIST: return "Set(iconlist)";
case CMD_ICONS: return "Set(icons)";
case CMD_HINTS: return "Set(hints)";
case CMD_LIST: return "Set(list)";
case CMD_MENU: return "Set(menu)";
case CMD_PARAM: return "Set(param)";
case CMD_REPAINT: return "Set(repaint)";
case CMD_LAYOUT: return "Set(layout)";
case CMD_STATUS: return "Set(status)";
case CMD_TEXT: return "Set(text)";
case CMD_TITLE: return "Set(title)";
case CMD_IMAGE: return "Set(image)";
case CMD_VIBRATE: return "Set(vibrate)";
case CMD_VOLUME: return "Set(volume)";
case CMD_COVER: return "Set(cover)";
case CMD_POPUP: return "Set(popup)";
case CMD_GETSCRSIZE: return "Get(screen_size)";
case CMD_GETPLTF: return "Get(model)";
case CMD_GETIMG: return "Get(is_exists)";
case CMD_GETCVRSIZE: return "Get(cover_size)";
case CMD_GETVER: return "Get(version)";
case CMD_GETCURSOR: return "Get(cursor)";
case CMD_GETPASS: return "Get(password)";
case CMD_GETPING: return "Get(ping)";
case CMD_GETICSIZE: return "Get(icon_size)";
case CMD_GETPADDING: return "Get(icon_padding)";
case CMD_CLOSECONN: return "CMD_CLOSECONN";
//case CMD_EXIT: return "CMD_EXIT";
case CMD_EDIT_FORM_IP: return "CMD_EDIT_FORM_IP"; // used for logging only ?
case CMD_EDIT_FORM_BT: return "CMD_EDIT_FORM_BT";
case CMD_LIST_UPDATE: return "CMD_LIST_UPDATE";
case CMD_SEARCH_DIALOG: return "CMD_SEARCH_DIALOG";
case CMD_SENSOR_DIALOG: return "CMD_SENSOR_DIALOG";
case CMD_CLOSE: return "CMD_CLOSE";
}
return "UNKNOWN";
}
public void handleGetCoverSizeCmd() {
Display d = context.getWindowManager().getDefaultDisplay();
queueCommand("CoverSize("+(d.getWidth()*2)/3+",)");
}
public void handleGetScreeenSizeCmd() {
Display display = context.getWindowManager().getDefaultDisplay();
boolean rotated = (display.getOrientation() == Surface.ROTATION_90 ||
display.getOrientation() == Surface.ROTATION_270);
String ori = (rotated ? "R" : "");
queueCommand("SizeX("+display.getWidth() +","+ori+")");
queueCommand("SizeY("+display.getHeight()+","+ori+")");
}
public void handleCommand(ProtocolMessage msg) {
int id = msg.id;
Vector cmdTokens = msg.tokens;
int stage = msg.stage;
log("handleCommand got:" + cmdStr(id) + " " + cmdTokens+"(cur screen is "+anyRemote.getScreenStr(anyRemote.getCurScreen())+")");
switch (id) {
case CMD_CLOSECONN:
log("handleCommand got: CMD_CLOSECONN");
disconnect(true);
break;
/*case CMD_EXIT:
controller.exit();
break;*/
case CMD_BG:
case CMD_CAPTION:
case CMD_FG:
case CMD_FONT:
case CMD_ICONS:
case CMD_HINTS:
case CMD_LAYOUT:
case CMD_STATUS:
case CMD_TITLE:
case CMD_VOLUME:
case CMD_COVER:
synchronized (cfTitle) {
controlDataProcess(cmdTokens);
// Create activity with (possibly) empty list
boolean isActive = (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM);
if (!(id == CMD_BG || id == CMD_FG || id == CMD_FONT) &&
!isActive) {
log("handleCommand switch to CONTROL_FORM");
context.setCurrentView(anyRemote.CONTROL_FORM, "");
}
if (isActive || !(id == CMD_BG || id == CMD_FG || id == CMD_FONT)) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
}
break;
case CMD_EFIELD:
if (cmdTokens.size() < 4) return;
efCaption = (String) cmdTokens.elementAt(1);
efLabel = (String) cmdTokens.elementAt(2);
efValue = (String) cmdTokens.elementAt(3);
efId = CMD_EFIELD;
sendToActivity(anyRemote.getCurScreen(),id,ProtocolMessage.FULL);
// CMD_EFIELD: result will be handled in handleEditFieldResult()
break;
case CMD_FSCREEN:
setFullscreen((String) cmdTokens.elementAt(1));
sendToActivity(anyRemote.getCurScreen(),id,ProtocolMessage.FULL);
break;
case CMD_POPUP:
popupState = false;
popupMsg.delete(0, popupMsg.length());
String op = (String) cmdTokens.elementAt(1);
if (op.equals("show")) {
popupState = true;
for (int i=2;i<cmdTokens.size();i++) {
if (i != 2) {
popupMsg.append(", ");
}
popupMsg.append((String) cmdTokens.elementAt(i));
}
}
sendToActivity(anyRemote.getCurScreen(),id,ProtocolMessage.FULL);
break;
case CMD_MENU:
menuProcess(cmdTokens, anyRemote.getCurScreen());
break;
case CMD_FMAN:
//controller.cScreen.setData(anyRemote.FMGR_FORM,cmdTokens,stage);
break;
case CMD_ICONLIST:
case CMD_LIST:
// setup List Screen activity persistent data
//if (anyRemote.getCurScreen() != anyRemote.LIST_FORM) {
// by default do not change system colors
// listCustomBackColor = false;
// listCustomTextColor = false;
//}
int switchTo = listDataProcess(id, cmdTokens, stage);
//log("handleCommand listDataProcess:" + switchTo);
boolean doClose = (cmdTokens.size() > 1 && ((String) cmdTokens.elementAt(1)).equals("close"));
if (anyRemote.logVisible()) {
if (doClose) {
context.setPrevView(anyRemote.CONTROL_FORM);
}
return;
}
if (doClose) {
// Close List Activity (even it was not started ;-)) and open ControlForm
log("handleCommand switch to CONTROL_FORM (L)");
context.setCurrentView(anyRemote.CONTROL_FORM, "");
return;
}
boolean isActive = (anyRemote.getCurScreen() == anyRemote.LIST_FORM);
// Create activity with (possibly) empty list
if ((switchTo == NOTUPDATE_SWITCH || switchTo == UPDATE_SWITCH) &&
!isActive) {
log("handleCommand switch to LIST_FORM");
context.setCurrentView(anyRemote.LIST_FORM, "");
}
int lid = ((switchTo == UPDATE_SWITCH || switchTo == UPDATE_NOTSWITCH) ? CMD_LIST_UPDATE : id);
if (isActive || (switchTo == NOTUPDATE_SWITCH || switchTo == UPDATE_SWITCH)) {
sendToActivity(anyRemote.LIST_FORM,lid,stage);
}
break;
case CMD_PARAM:
for (int i = 1; i < cmdTokens.size(); ) {
String tag = (String) cmdTokens.elementAt(i);
if (tag.equals("icon_padding")) {
i++;
if (i >= cmdTokens.size()) return;
log("icon_padding "+((String) cmdTokens.elementAt(i)));
cfPadding= Integer.parseInt(((String) cmdTokens.elementAt(i)));
if (cfPadding < 0) cfPadding = 0;
Display display = context.getWindowManager().getDefaultDisplay();
if (cfPadding >= display.getWidth()/6) cfPadding = display.getWidth()/6;
if (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
} else if (tag.equals("icon_size")) {
i++;
if (i >= cmdTokens.size()) return;
cfIconSizeOverride = Integer.parseInt(((String) cmdTokens.elementAt(i)));
if (cfIconSizeOverride < 0) cfIconSizeOverride = -1; // == do not use
Display display = context.getWindowManager().getDefaultDisplay();
if (cfIconSizeOverride >= display.getWidth()/3) cfIconSizeOverride = display.getWidth()/3;
if (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
}
i++;
}
break;
case CMD_REPAINT:
if (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
break;
case CMD_TEXT:
boolean needSwitch = textDataProcess(cmdTokens, stage);
boolean doCloset = (cmdTokens.size() > 1 && ((String) cmdTokens.elementAt(1)).equals("close"));
if (anyRemote.logVisible()) {
if (doCloset) {
context.setPrevView(anyRemote.CONTROL_FORM);
}
return;
}
if (doCloset) {
// Close Text Activity (even it was not started ;-)) and open ControlForm
log("handleCommand switch to CONTROL_FORM (T)");
context.setCurrentView(anyRemote.CONTROL_FORM, "");
return;
}
// Create activity with (possibly) empty list
int scr = anyRemote.getCurScreen();
if (needSwitch && scr != anyRemote.TEXT_FORM) {
log("handleCommand switch to TEXT_FORM");
context.setCurrentView(anyRemote.TEXT_FORM, "");
}
if (needSwitch || scr == anyRemote.TEXT_FORM) {
sendToActivity(anyRemote.TEXT_FORM,id,stage);
}
break;
case CMD_VIBRATE:
int vi = 2;
if (cmdTokens.size() > 1) {
try {
vi = Integer.parseInt((String) cmdTokens.elementAt(1));
} catch (NumberFormatException e) {
}
if (vi <= 0) {
break;
}
if (vi > 300) {
vi = 300;
}
}
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(vi*100);
break;
case CMD_IMAGE:
boolean doCloseW = false;
if (cmdTokens.size() < 2) {
log("Improper image command");
return;
}
if (((String) cmdTokens.elementAt(1)).equals("close")) {
doCloseW = true;
}
if (anyRemote.logVisible()) {
if (doCloseW) {
context.setPrevView(anyRemote.CONTROL_FORM);
}
return;
}
if (doCloseW) {
// Close WinManager Activity (even it was not started ;-)) and open ControlForm
log("handleCommand switch to CONTROL_FORM (W)");
context.setCurrentView(anyRemote.CONTROL_FORM, "");
return;
}
if (((String) cmdTokens.elementAt(1)).equals("window")) {
// Create activity
if (anyRemote.getCurScreen() != anyRemote.WMAN_FORM) {
log("handleCommand switch to WMAN_FORM");
context.setCurrentView(anyRemote.WMAN_FORM, "");
}
sendToActivity(anyRemote.WMAN_FORM,id,stage);
} else if (((String) cmdTokens.elementAt(1)).equals("icon")) {
// redraw ControlForm if it is active
if (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
// redraw ListForm if it is active (list can show icons!)
if (anyRemote.getCurScreen() == anyRemote.LIST_FORM) {
sendToActivity(anyRemote.LIST_FORM,id,stage);
}
} else if (((String) cmdTokens.elementAt(1)).equals("cover")) {
// redraw ControlForm if it is active
if (anyRemote.getCurScreen() == anyRemote.CONTROL_FORM) {
sendToActivity(anyRemote.CONTROL_FORM,id,stage);
}
} else if (((String) cmdTokens.elementAt(1)).equals("remove")) {
if (cmdTokens.size() < 3) {
log("Improper image remove command");
return;
}
String rm = (String) cmdTokens.elementAt(2);
File store = Environment.getExternalStorageDirectory();
if (rm.equals("icons") || rm.equals("all")) {
log("Remove all downloaded icons");
File d = new File(store, "Android/data/anyremote.client.android/files/icons");
emptyDir(d);
}
if (rm.equals("covers") || rm.equals("all")) {
log("Remove all downloaded covers Android/data/anyremote.client.android/files/covers");
File d = new File(store, "Android/data/anyremote.client.android/files/covers");
emptyDir(d);
}
} else if (((String) cmdTokens.elementAt(1)).equals("clear_cache")) {
//log("Clear image cache");
anyRemote.clearCache();
clearRequested();
}
break;
case CMD_GETSCRSIZE:
handleGetScreeenSizeCmd();
break;
case CMD_GETCVRSIZE:
handleGetCoverSizeCmd();
break;
case CMD_GETICSIZE:
synchronized (cfTitle) {
queueCommand("IconSize("+(cfIconSizeOverride >= 0 ? cfIconSizeOverride : cfIconSize)+",)");
}
break;
case CMD_GETPADDING:
synchronized (cfTitle) {
queueCommand("IconPadding("+cfPadding+",)");
}
break;
case CMD_GETVER:
try {
ComponentName comp = new ComponentName(context, this.getClass());
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(), 0);
queueCommand("Version(,"+pinfo.versionName+")");
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
queueCommand("Version(,unknown)");
}
break;
case CMD_GETPING:
queueCommand("Ping");
if (cmdTokens.size() > 1) { // get timeout
keepaliveTimeout = Integer.parseInt(((String) cmdTokens.elementAt(1)));
if (keepaliveTimeout > 0) {
scheduleKeepaliveTask();
}
}
if (keepaliveTimeout > 0) {
keepaliveCounter++;
}
break;
case CMD_GETPASS:
log("CMD_GETPASS");
// strip possible \n
if (currentConnPass.length() > 0 && currentConnPass.charAt(currentConnPass.length() - 1) == '\n') {
currentConnPass = currentConnPass.substring(0, currentConnPass.length() - 1);
}
if (currentConnPass.length() > 0 && currentConnPass.charAt(0) == '\n') {
currentConnPass = currentConnPass.substring(1);
}
if (autoPass || currentConnPass.equals("")) {
log("ASK FOR PASS");
sendToActivity(anyRemote.getCurScreen(),id,stage);
//result will be handled in handleEditFieldResult()
} else {
log("USE PASS >"+currentConnPass+"<");
autoPass = true;
queueCommand("_PASSWORD_(,"+currentConnPass+")");
}
break;
case CMD_GETCURSOR:
/*if (controller.cScreen.wm != null) {
controller.cScreen.wm.sendCursorPos();
}*/
break;
case CMD_GETPLTF:
queueCommand("Model(,"+android.os.Build.MODEL+"/Android-"+android.os.Build.VERSION.RELEASE+")");
break;
case CMD_GETIMG:
// old format Get(is_exists,sz,name)
// new format Get(is_exists,[icon,sz,name]|cover,name])
String item2 = (String) cmdTokens.elementAt(1);
boolean isIcon = true;
String size;
String name;
if (item2.equals("icon")) {
size = (String) cmdTokens.elementAt(2);
name = (String) cmdTokens.elementAt(3);
} else if (item2.equals("cover")) {
isIcon = false;
size = "";
name = (String) cmdTokens.elementAt(2);
} else {
size = (String) cmdTokens.elementAt(1);
name = (String) cmdTokens.elementAt(2);
}
if (isIcon) {
int iconId = anyRemote.icon2int(name);
boolean isExists = false;
if (iconId == R.drawable.icon) { // no such icon
File dir = Environment.getExternalStorageDirectory();
File iFile = new File(dir, "Android/data/anyremote.client.android/files/icons/"+name+".png");
isExists = iFile.canRead();
} else {
isExists = true;
}
String resp;
if (isExists) {
resp = "IconExists("+size+","+name+")";
} else {
resp = "IconNotExists("+size+","+name+")";
}
queueCommand(resp);
} else {
boolean isExists = false;
File dir = Environment.getExternalStorageDirectory();
File iFile = new File(dir, "Android/data/anyremote.client.android/files/covers/"+name+".png");
isExists = iFile.canRead();
String resp;
if (isExists) {
resp = "CoverExists(,"+name+")";
} else {
resp = "CoverNotExists(,"+name+")";
}
queueCommand(resp);
}
break;
default:
log("handleCommand: Command or handler unknown");
}
}
public synchronized void sendToActivity(int activity, int id, int stage) {
log("sendToActivity to "+anyRemote.getScreenStr(activity)+" "+cmdStr(id));
QueueMessage pm = new QueueMessage();
pm.activity = activity;
pm.id = id;
pm.stage = stage;
pm.attemptsToSend = 0;
synchronized (msgQueue) {
msgQueue.add(0,pm);
}
processMessageQueue();
}
public int messageQueueSize() {
synchronized (msgQueue) {
return msgQueue.size();
}
}
private synchronized void processMessageQueue() {
final Iterator<QueueMessage> msgItr = msgQueue.iterator();
while (msgItr.hasNext()) {
final QueueMessage pm = msgItr.next();
boolean sent = false;
synchronized (actHandlers) {
final Iterator<ArHandler> itr = actHandlers.iterator();
log("processMessageQueue MSG " + cmdStr(pm.id) + " handlers #" + actHandlers.size());
while (itr.hasNext()) {
try {
final ArHandler handler = itr.next();
if (pm.activity < 0 || // send to all
handler.actId == pm.activity) {
log("processMessageQueue MSG " + cmdStr(pm.id) +
" to " + anyRemote.getScreenStr(pm.activity) +
" SENT (attempt " + pm.attemptsToSend + ") to "+
anyRemote.getScreenStr(handler.actId));
InfoMessage im = new InfoMessage();
im.id = pm.id;
im.stage = pm.stage;
Message msg = handler.hdl.obtainMessage(im.id, im);
msg.sendToTarget();
sent = true;
}
} catch (Exception e) {
log("processMessageQueue exception " + e.getMessage());
}
}
}
if (sent) {
// just drop it from queue
synchronized (msgQueue) {
msgItr.remove();
}
break;
} else {
log("processMessageQueue MSG " + cmdStr(pm.id) + " to " + anyRemote.getScreenStr(pm.activity) + " WAIT");
pm.attemptsToSend++;
if ((pm.id == CMD_CLOSE && (pm.activity == anyRemote.NO_FORM || pm.activity == -1)) ||
pm.attemptsToSend > MAX_ATTEMPTS) {
// just drop it from queue
log("processMessageQueue MSG " + cmdStr(pm.id) + " to " + anyRemote.getScreenStr(pm.activity) + " DROP");
synchronized (msgQueue) {
msgItr.remove();
}
break;
}
}
}
if (msgQueue.size() > 0) {
// Schedule new attempts to send
log("processMessageQueue schedule next iteration (have " + msgQueue.size() + " events)");
MainLoop.schedule(new TimerTask() {
public void run() {
processMessageQueue();
}
});
}
}
private synchronized void scheduleKeepaliveTask() {
MainLoop.schedule(
new TimerTask() {
public void run() {
keepaliveTask();
}
},
(long) (keepaliveTimeout * 3000)); // x2 is not enough sometimes
}
private synchronized void keepaliveTask() {
if (keepaliveTimeout > 0) {
log("keepaliveTask test keepalive");
if (keepaliveCounter == 0) {
log("keepaliveTask seems connection is lost, do disconnect");
disconnect(true);
} else {
keepaliveCounter = 0;
scheduleKeepaliveTask();
}
}
}
public void handleEditFieldResult(int id, String button, String value) {
if (id == Dispatcher.CMD_GETPASS) {
queueCommand("_PASSWORD_(,"+value+")");
setPassForConnection(value);
} else {
queueCommand(button + "(0," + value + ")");
}
}
public void setPassForConnection(String pass) {
SharedPreferences preference = context.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preference.edit();
String UP = currentConnection + "\n" + pass;
editor.putString(currentConnName, UP);
editor.commit();
}
public Vector<Address> loadPrefs() {
log("loadPrefs");
SharedPreferences preference = context.getPreferences(Context.MODE_PRIVATE);
Vector<Address> addresses = new Vector<Address>();
try {
Map<String, String> datam = (Map<String, String>) preference.getAll();
log("loadPrefs got #"+datam.size());
Iterator<Map.Entry<String, String>> it = datam.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pairs = (Map.Entry<String, String>) it.next();
String key = (String) pairs.getKey();
String cf_url_pass = (String) pairs.getValue();
//log("loadPrefs k/v >"+key+"< >"+cf_url_pass+"<");
if (key.equals(M_SENSOR)) { // special cases
useGyroscope = (cf_url_pass.compareTo("g") == 0);
} else {
// format a|c+:+address+\n+pass
// old format is address+\n+pass
boolean autoconnect = cf_url_pass.startsWith("a");
String url_pass = (cf_url_pass.charAt(1) == ':' ?
cf_url_pass.substring(2) :
cf_url_pass);
int p = url_pass.lastIndexOf('\n');
if (p > 0) {
Address a = new Address();
a.name = key;
a.URL = url_pass.substring(0, p).trim();
a.pass = url_pass.substring(p+1);
a.autoconnect = autoconnect;
//log("loadPrefs >"+cf_url_pass.charAt(0)+"< >"+a.name+"< >"+a.URL+"< >"+a.pass+"<");
addresses.add(a);
}
}
}
} catch(Exception z) { }
return addresses;
}
boolean sensorGyroscope() {
return useGyroscope;
}
public void setSensorType(boolean useG) {
if (useGyroscope != useG) {
useGyroscope = useG;
SharedPreferences preference = context.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preference.edit();
editor.putString(M_SENSOR, (useG ? "g" : "a"));
editor.commit();
}
}
public void cleanAddress(String name) {
log("cleanAddress "+name);
SharedPreferences preference = context.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preference.edit();
editor.remove(name);
editor.commit();
}
// save new address in preferences
public void addAddress(String name, String URL, String pass, boolean autoConnect) {
//log("addAddress "+name+"/"+URL+"/"+pass);
SharedPreferences preference = context.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preference.edit();
if (autoConnect) { // only one peer can have auto connect flag
try {
Map<String, String> datam = (Map<String, String>) preference.getAll();
Iterator<Map.Entry<String, String>> it = datam.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pairs = (Map.Entry<String, String>) it.next();
// format a|c+:+address+\n+pass
// old format is address+\n+pass
String cf_url_pass = (String) pairs.getValue();
boolean autoconnect = cf_url_pass.startsWith("a");
if (autoconnect) {
cf_url_pass = "c" + cf_url_pass.substring(1);
editor.putString((String) pairs.getKey(), cf_url_pass);
}
}
} catch(Exception z) { }
}
String UP = (autoConnect ? "a:" : "c:") + URL.trim() + "\n" + pass;
log("addAddress commit "+name+"/"+UP);
editor.putString(name, UP);
editor.commit();
}
private void sendMessage(String command) {
if (connection != null && !connection.isClosed()) {
//log("sendMessage " + command);
connection.send(command+";\r");
}
}
public void queueCommand(int keycode, boolean pressed) {
log("queueCommand "+keycode +" " + pressed);
String key = "";
switch (keycode) {
case ControlScreen.KEY_NUM1: key = "1";break;
case ControlScreen.KEY_NUM2: key = "2";break;
case ControlScreen.KEY_NUM3: key = "3";break;
case ControlScreen.KEY_NUM4: key = "4";break;
case ControlScreen.KEY_NUM5: key = "5";break;
case ControlScreen.KEY_NUM6: key = "6";break;
case ControlScreen.KEY_NUM7: key = "7";break;
case ControlScreen.KEY_NUM8: key = "8";break;
case ControlScreen.KEY_NUM9: key = "9";break;
case ControlScreen.KEY_STAR: key = "*";break;
case ControlScreen.KEY_NUM0: key = "0";break;
case ControlScreen.KEY_POUND: key = "#";break;
default:
}
if (key.length() > 0) {
sendMessage("+CKEV: " + key + "," + (pressed ? "1" : "0"));
}
}
public void queueCommand(String key, boolean pressed) {
//log("queueCommand "+key +" " + pressed);
if (key.length() > 0) {
sendMessage("+CKEV: " + key + "," + (pressed ? "1" : "0"));
}
}
public void queueCommand(String message) {
sendMessage("Msg:" + message);
}
public void setFullscreen(String option) {
if (option.startsWith("on")) {
if (fullscreen) return;
fullscreen = true;
} else if (option.startsWith("off")) {
if (!fullscreen) return;
fullscreen = false;
} else if (option.startsWith("toggle")) {
fullscreen = !fullscreen;
}
}
//public void setFullscreen(String option, arActivity act) {
//
// setFullscreen(option);
// setFullscreen(act);
//}
public void setFullscreen(arActivity act) {
if (fullscreen) {
act.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
act.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
act.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
act.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
public void log(String msg) {
anyRemote._log("Dispatcher",msg);
}
public synchronized void addMessageHandler(ArHandler h) {
log("addMessageHandler");
synchronized (actHandlers) {
if (!actHandlers.contains(h)) {
log("addMessageHandler DONE");
actHandlers.add(h);
}
}
}
public synchronized void removeMessageHandler(ArHandler h) {
synchronized (actHandlers) {
actHandlers.remove(h);
}
}
//
// Control Screen activity persistent data handling
//
private void controlDataProcess(Vector vR) {
//log("processData >"+vR+"<");
int id = (Integer) vR.elementAt(0);
switch (id) {
case CMD_LAYOUT:
if (vR.size() < 2) {
return;
}
controlSetSkin(vR);
break;
case CMD_STATUS:
if (vR.size() < 2) {
return;
}
cfStatus = (String) vR.elementAt(1);
break;
case CMD_TITLE:
if (vR.size() < 2) {
return;
}
cfTitle = (String) vR.elementAt(1);
break;
case CMD_CAPTION:
if (vR.size() < 2) {
return;
}
cfCaption = (String) vR.elementAt(1);
break;
case CMD_ICONS:
if (vR.size() < 2) {
return;
}
controlSetIconLayout(vR);
break;
case CMD_HINTS:
if (vR.size() < 2) {
return;
}
controlSetHints(vR);
break;
case CMD_BG:
cfBkgr = anyRemote.parseColor(vR,1);
break;
case CMD_FG:
cfFrgr = anyRemote.parseColor(vR,1);
break;
case CMD_FONT:
if (vR.size() < 2) {
return;
}
controlSetFontParams(vR);
break;
case CMD_FSCREEN:
if (vR.size() < 2) {
return;
}
setFullscreen((String) vR.elementAt(1));
break;
case CMD_VOLUME:
if (vR.size() < 2) {
return;
}
cfVolume = (String) vR.elementAt(1);
break;
case CMD_COVER:
if (vR.size() < 3) {
if (vR.size() == 2 && !((String) vR.elementAt(1)).equals("clear")) {
log("processData wrong Set(cover...) command");
}
cfCover = null;
cfNamedCover = "";
} else {
if (((String) vR.elementAt(1)).equals("noname")) {
cfCover = (Bitmap) vR.elementAt(2);
cfNamedCover = "";
} else {
cfCover = null;
cfNamedCover = (String) vR.elementAt(2);
}
}
break;
}
}
private void controlSetSkin(Vector vR) {
String name = (String) vR.elementAt(1);
//useCover = false;
//cover = null;
//boolean newVolume = false;
//int newSize = icSize;
cfUseJoystick = true;
cfUpEvent = "UP";
cfDownEvent = "DOWN";
cfInitFocus = 5;
boolean oneMore = false;
for (int i=2;i<vR.size();) {
String oneParam = (String) vR.elementAt(i);
if (oneMore) {
try {
cfInitFocus = btn2int(oneParam);
} catch (NumberFormatException e) {
cfInitFocus = -1;
}
oneMore = false;
} else if (oneParam.equals("joystick_only")) {
cfUseJoystick = true;
//useKeypad = false;
} else if (oneParam.equals("keypad_only")) {
cfUseJoystick = false;
//useKeypad = true;
} else if (oneParam.equals("ticker")) {
//newTicker = true;
} else if (oneParam.equals("noticker")) {
//newTicker = false;
} else if (oneParam.equals("volume")) {
//newVolume = true;
} else if (oneParam.equals("size16")) {
//newSize = 16;
} else if (oneParam.equals("size32")) {
//newSize = 32;
} else if (oneParam.equals("size48")) {
//newSize = 48;
} else if (oneParam.equals("size64")) {
//newSize = 64;
} else if (oneParam.equals("size128")) {
//newSize = 128;
} else if (oneParam.equals("choose")) {
oneMore = true;
} else if (oneParam.equals("up")) {
i++;
if (i<vR.size()) {
cfUpEvent = (String) vR.elementAt(i);
}
} else if (oneParam.equals("down")) {
i++;
if (i<vR.size()) {
cfDownEvent = (String) vR.elementAt(i);
}
}
i++;
}
if (name.equals("default") ||
name.equals("3x4")) {
cfSkin = ControlScreen.SK_DEFAULT;
} else if (name.equals("7x1") ||
name.equals("bottomline")) {
cfSkin = ControlScreen.SK_BOTTOMLINE;
}
}
private void controlSetIconLayout(Vector data) {
if (data.size() == 0) {
return;
}
// want to support new&old format for now:
// Set(icons,caption,1,icon,...)
// Set(icons,1,icon,...)
int start = 1;
if (btn2int((String) data.elementAt(start)) < 0) {
start++;
}
if (start == 2 && !((String) data.elementAt(1)).equals("SAME")) {
cfCaption = (String) data.elementAt(1);
}
if (data.size() < start+1) {
return;
}
int maxIcon = (cfSkin == ControlScreen.SK_BOTTOMLINE ? ControlScreen.NUM_ICONS_BTM : ControlScreen.NUM_ICONS);
for (int idx=start;idx<data.size()-1;idx+=2) {
try {
int i = btn2int((String) data.elementAt(idx));
if (i >= 0 || i < maxIcon) {
cfIcons[i] = (String) data.elementAt(idx+1);
log("controlSetIconLayout "+i+" -> "+cfIcons[i]);
}
} catch (Exception e) { }
}
}
private void controlSetHints(Vector data) {
if (data.size() < 2) {
return;
}
for (int idx=1;idx<data.size()-1;idx+=2) {
try {
int i = btn2int((String) data.elementAt(idx));
if (i >= 0 || i < ControlScreen.NUM_ICONS) {
cfHints[i] = (String) data.elementAt(idx+1);
log("controlSetHints "+i+" -> "+cfHints[i]);
}
} catch (Exception e) { }
}
}
private void controlSetFontParams(Vector defs) {
boolean bold = false;
boolean italic = false;
float size = SIZE_MEDIUM;
boolean setSize = false;
int start = 1;
while (start<defs.size()) {
String spec = (String) defs.elementAt(start);
if (spec.equals("plain")) {
//style = Font.STYLE_PLAIN;
} else if (spec.equals("bold")) {
bold = true;
} else if (spec.equals("italic")) {
italic = true;
} else if (spec.equals("underlined")) {
//style = (style == Font.STYLE_PLAIN ? Font.STYLE_UNDERLINED : style|Font.STYLE_UNDERLINED);
} else if (spec.equals("small")) {
size = Dispatcher.SIZE_SMALL;
setSize = true;
} else if (spec.equals("medium")) {
size = Dispatcher.SIZE_MEDIUM;
setSize = true;
} else if (spec.equals("large")) {
size = Dispatcher.SIZE_LARGE;
setSize = true;
} else if (spec.equals("monospace")) {
//face = Font.FACE_MONOSPACE;
} else if (spec.equals("system")) {
//face = Font.FACE_SYSTEM;
} else if (spec.equals("proportional")) {
//face = Font.FACE_PROPORTIONAL;
//} else {
// controller.showAlert("Incorrect font "+spec);
}
start++;
}
if (bold && italic) {
cfTFace = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC);
} else if (bold) {
cfTFace = Typeface.defaultFromStyle(Typeface.BOLD);
} else if (italic) {
cfTFace = Typeface.defaultFromStyle(Typeface.ITALIC);
} else {
cfTFace = Typeface.defaultFromStyle(Typeface.NORMAL);
}
if (setSize) {
cfFSize = size;
}
}
private int btn2int(String btn) {
int i = -1;
if (btn.equals("*")) {
i=9;
} else if (btn.equals("#")) {
i=11;
} else {
try {
i = Integer.parseInt(btn) - 1;
if (i == -1) { // 0 was parsed
i = 10;
}
} catch (NumberFormatException e) { }
}
return i;
}
//
// List Screen activity persistent data handling
//
//
// list|iconlist, add|replace|!close!|clear|!show![,Title,item1,...itemN]
//
// Set(list,close) does NOT processed here !
//
// returns 0 - do not update data source, do not switch to list screen
// 1 - need update data source + switch to list screen
// 2 - need update data, do not switch to list screen
//
private int listDataProcess(int id, Vector vR, int stage) {
log("listDataProcess "+id+" "+vR);
if (stage == ProtocolMessage.INTERMED ||
stage == ProtocolMessage.LAST) {
// get next portion of Set(list,add/replace ...)
listAdd(id, vR, 0, false);
return UPDATE_SWITCH;
}
String oper = (String) vR.elementAt(1);
if (oper.equals("clear")) {
listClean();
return UPDATE_NOTSWITCH;
} else if (oper.equals("close")) {
// here processed only "clear" part of the command
if (vR.size() > 2 && ((String) vR.elementAt(2)).equals("clear")) {
listClean();
}
return NOTUPDATE_NOTSWITCH;
} else if (oper.equals("fg")) {
int color = anyRemote.parseColor(vR,2);
listText = color;
listCustomTextColor = true;
return UPDATE_NOTSWITCH;
} else if (oper.equals("bg")) {
int color = anyRemote.parseColor(vR,2);
listBkgr = color;
listCustomBackColor = true;
return UPDATE_NOTSWITCH;
} else if (oper.equals("font")) {
listSetFont(vR);
return UPDATE_NOTSWITCH;
} else if (oper.equals("caption")) {
if (vR.size() > 2) {
listTitle = (String) vR.elementAt(2);;
}
return UPDATE_SWITCH;
} else if (oper.equals("select")) {
try {
int i = Integer.parseInt((String) vR.elementAt(2))-1;
if (i>0) {
listSelectPos = i;
}
} catch(Exception z) {
listSelectPos = -1;
}
return UPDATE_SWITCH;
} else if (oper.equals("icon")) {
try {
listIcon = (String) vR.elementAt(2);
} catch(Exception z) {
listIcon = "";
}
return UPDATE_NOTSWITCH;
} else if (oper.equals("add") || oper.equals("replace")) {
String title = (String) vR.elementAt(2);
if (oper.equals("replace")) {
listClean();
}
if (!title.equals("SAME")) {
listTitle = title;
}
listAdd(id, vR, 3, (stage == ProtocolMessage.FULL));
return UPDATE_SWITCH;
} else if (oper.equals("show")) {
// nothing to do
return NOTUPDATE_SWITCH;
} else {
log("processList: ERROR improper command >"+oper+"<");
}
return NOTUPDATE_NOTSWITCH;
}
private void listAdd(int id, Vector vR, int start, boolean fullCmd) {
//log("addToList "+vR);
int end = vR.size();
if (!fullCmd) {
end -= 1;
}
for (int idx=start;idx<end;idx++) {
String item = (String) vR.elementAt(idx);
if (start == 0 && idx == 0) {
item = listBufferedItem.toString() + item;
listBufferedItem.delete(0, listBufferedItem.length());
}
String[] items = item.split("\n");
for (int i=0;i<items.length;i++) {
String subitem = items[i];
if (!subitem.equals("") && ! (subitem.length() == 1 && subitem.charAt(0) == '\n')) {
listAddWithIcon(id, subitem);
}
}
}
if (!fullCmd) {
listBufferedItem.append((String) vR.elementAt(end));
}
}
private void listAddWithIcon(int id, String content) {
ListItem item = new ListItem();
int idx = (id == CMD_ICONLIST ? content.indexOf(":") : 0);
if (idx > 0) {
item.icon = content.substring(0,idx).trim();
item.text = content.substring(idx+1).trim().replace('\r', ',');
} else {
item.icon = null;
item.text = content;
}
synchronized (listContent) {
listContent.add(item);
}
}
private void listClean() {
log("listClean");
listSelectPos = -1;
synchronized (listContent) {
listContent.clear();
}
listBufferedItem.delete(0, listBufferedItem.length());
}
private void listSetFont(Vector defs) {
int start = 2;
while(start<defs.size()) {
String spec = (String) defs.elementAt(start);
if (spec.equals("small")) {
listFSize = Dispatcher.SIZE_SMALL;
} else if (spec.equals("medium")) {
listFSize = Dispatcher.SIZE_MEDIUM;
} else if (spec.equals("large")) {
listFSize = Dispatcher.SIZE_LARGE;
} else {
listFSize = -1;
}
start++;
}
}
//
// Text Screen activity persistent data handling
//
// Set(text,add,title,_text_) 3+text
// Set(text,replace,title,_text_) 3+text
// Set(text,fg|bg,r,g,b) 6
// Set(text,font,small|medium|large) 3
// Set(text,close[,clear]) 2 or 3
// Set(text,wrap,on|off) 3
// Set(text,show)
//
// Set(list,close) does NOT processed here !
//
private boolean textDataProcess(Vector vR, int stage) { // message = add|replace|show|clear,title,long_text
//log("textDataProcess VSIZE "+vR.size() + " stage " + stage);
if (vR.size() == 0) {
return false;
}
if (stage == ProtocolMessage.INTERMED) {
textContent.append((String) vR.elementAt(0));
return true;
} else if (stage == ProtocolMessage.LAST) {
if (vR.size() > 2) {
textContent.append((String) vR.elementAt(3));
}
return true;
}
String oper = (String) vR.elementAt(1);
if (oper.equals("clear")) {
textContent.delete(0, textContent.length());
return false;
} else if (oper.equals("add") ||
oper.equals("replace")) {
if (!((String) vR.elementAt(2)).equals("SAME")) {
textTitle = (String) vR.elementAt(2);
}
if (oper.equals("replace")) {
textContent.delete(0, textContent.length());
}
textContent.append((String) vR.elementAt(3));
return true;
} else if (oper.equals("fg")) {
textFrgr = anyRemote.parseColor(vR,2);
return false;
} else if (oper.equals("bg")) {
textBkgr = anyRemote.parseColor(vR,2);
return false;
} else if (oper.equals("font")) {
textFontParams(vR);
return false;
} else if (oper.equals("caption")) {
if (vR.size() > 2) {
textTitle = (String) vR.elementAt(2);;
}
return true;
//} else if (oper.equals("wrap")) {
// not supported
//return false;
} else if (oper.equals("close")) {
if (vR.size() > 2 && ((String) vR.elementAt(2)).equals("clear")) {
textContent.delete(0, textContent.length());
}
} else if (!oper.equals("show")) {
return false; // seems command improperly formed
}
return true;
}
private void textFontParams(Vector defs) {
boolean bold = false;
boolean italic = false;
float size = Dispatcher.SIZE_MEDIUM;
int start = 2;
while(start<defs.size()) {
String spec = (String) defs.elementAt(start);
if (spec.equals("plain")) {
//style = Font.STYLE_PLAIN;
} else if (spec.equals("bold")) {
bold = true;
} else if (spec.equals("italic")) {
italic = true;
} else if (spec.equals("underlined")) {
//style = (style == Font.STYLE_PLAIN ? Font.STYLE_UNDERLINED : style|Font.STYLE_UNDERLINED);
} else if (spec.equals("small")) {
size = Dispatcher.SIZE_SMALL;
} else if (spec.equals("medium")) {
size = Dispatcher.SIZE_MEDIUM;
} else if (spec.equals("large")) {
size = Dispatcher.SIZE_LARGE;
} else if (spec.equals("monospace")) {
//face = Font.FACE_MONOSPACE;
} else if (spec.equals("system")) {
//face = Font.FACE_SYSTEM;
} else if (spec.equals("proportional")) {
//face = Font.FACE_PROPORTIONAL;
//} else {
// controller.showAlert("Incorrect font "+spec);
}
start++;
}
if (bold && italic) {
textTFace = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC);
} else if (bold) {
textTFace = Typeface.defaultFromStyle(Typeface.BOLD);
} else if (italic) {
textTFace = Typeface.defaultFromStyle(Typeface.ITALIC);
} else {
textTFace = Typeface.defaultFromStyle(Typeface.NORMAL);
}
textFSize = size;
}
//
// Menu data handling
//
public void menuProcess(Vector vR, int screen) {
anyRemote._log("Dispatcher", "menuProcess "+screen+" "+vR);
String oper = (String) vR.elementAt(1);
if (oper.equals("clear")) {
menuClean(screen);
} else if (oper.equals("add") || oper.equals("replace")) {
if (oper.equals("replace")) {
menuClean(screen);
menuAddDefault(screen);
}
menuAdd(vR, screen);
}
}
void menuClean(int screen) {
switch(screen) {
case anyRemote.CONTROL_FORM:
cfMenu.clear();
break;
case anyRemote.TEXT_FORM:
case anyRemote.LOG_FORM:
textMenu.clear();
break;
case anyRemote.LIST_FORM:
listMenu.clear();
break;
case anyRemote.WMAN_FORM:
winMenu.clear();
break;
}
}
void menuAdd(Vector from, int screen) {
anyRemote._log("Dispatcher", "menuAdd "+screen+" "+from);
for (int idx=2;idx<from.size();idx++) {
String item = (String) from.elementAt(idx);
if (item.length() > 0) {
switch(screen) {
case anyRemote.CONTROL_FORM:
//anyRemote._log("Dispatcher", "menuAdd cfMenu "+item);
cfMenu.add(item);
break;
case anyRemote.TEXT_FORM:
textMenu.add(item);
break;
case anyRemote.LIST_FORM:
listMenu.add(item);
break;
case anyRemote.WMAN_FORM:
winMenu.add(item);
break;
}
}
}
}
void menuReplaceDefault(int screen) {
menuClean(screen);
menuAddDefault(screen);
}
private void menuAddDefault(int screen) {
switch(screen) {
case anyRemote.CONTROL_FORM:
cfMenu.add(context.getString(R.string.disconnect_item));
cfMenu.add(context.getString(R.string.exit_item));
cfMenu.add(context.getString(R.string.mouse_item));
cfMenu.add(context.getString(R.string.keyboard_item));
cfMenu.add(context.getString(R.string.log_item));
break;
case anyRemote.TEXT_FORM:
textMenu.add(context.getString(R.string.back_item));
break;
case anyRemote.LIST_FORM:
listMenu.add(context.getString(R.string.back_item));
break;
case anyRemote.WMAN_FORM:
winMenu.add(context.getString(R.string.back_item));
break;
/*case anyRemote.MOUSE_FORM:
mouseMenu.add(context.getString(R.string.back_item));
break;
case anyRemote.KEYBOARD_FORM:
keyboardMenu.add(context.getString(R.string.back_item));
break;
case anyRemote.WEB_FORM:
webMenu.add(context.getString(R.string.disconnect_item));
break;
case anyRemote.LOG_FORM:
textMenu.add(context.getString(R.string.clear_log_item));
textMenu.add(context.getString(R.string.report_bug_item));
textMenu.add(context.getString(R.string.back_item));
break;*/
}
}
Vector<String> getMenu() {
int screen = anyRemote.getCurScreen();
switch(screen) {
case anyRemote.CONTROL_FORM:
return cfMenu;
case anyRemote.TEXT_FORM:
//case anyRemote.LOG_FORM:
return textMenu;
case anyRemote.LIST_FORM:
return listMenu;
/*case anyRemote.MOUSE_FORM:
return mouseMenu;
case anyRemote.KEYBOARD_FORM:
return keyboardMenu;
case anyRemote.WEB_FORM:
return webMenu;*/
case anyRemote.WMAN_FORM:
return winMenu;
}
return null;
}
public void autoUploadIcon(String name) {
synchronized (autoUploadedI) {
if (!autoUploadedI.contains(name)) {
anyRemote._log("Dispatcher", "autoUploadIcon request for "+name);
autoUploadedI.add(name);
queueCommand("_GET_ICON_(128,"+ name +")");
}
}
}
public void autoUploadCover(String name) {
synchronized (autoUploadedC) {
if (!autoUploadedC.contains(name)) {
anyRemote._log("Dispatcher", "autoUploadCover request for "+name);
autoUploadedC.add(name);
Display d = context.getWindowManager().getDefaultDisplay();
queueCommand("_GET_COVER_("+(d.getWidth()*2)/3+","+ name +")");
}
}
}
public void clearRequested() {
synchronized (autoUploadedI) {
autoUploadedI.clear();
}
synchronized (autoUploadedC) {
autoUploadedC.clear();
}
}
private void emptyDir(File dir) {
anyRemote._log("Dispatcher", "cleanup directory "+dir.getAbsolutePath());
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (int i=0;i<files.length;i++) {
File one = files[i];
//anyRemote._log("Dispatcher", "remove "+one.getAbsolutePath());
one.delete();
}
} else {
anyRemote._log("Dispatcher", "no directory "+dir.getAbsolutePath());
}
}
}