Subversion Repositories HomeAutomation

Rev

Blame | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  * File created by arune
  3.  * at 2005-jan-09 16:54:44
  4.  */
  5. package Macbeth.Modules.modMenuSystem;
  6.  
  7. import Macbeth.System.*;
  8. import Macbeth.Utilities.*;
  9. import Macbeth.XML.XMLDataHandler;
  10. import Macbeth.XML.XMLParser;
  11. import Macbeth.Utilities.*;
  12. import Macbeth.Modules.modGenRoomControl.GenRoomObject;
  13. import Macbeth.Net.*;
  14.  
  15. import java.util.*;
  16.  
  17. import javax.swing.*;
  18. import javax.swing.Timer;
  19.  
  20. import org.xml.sax.SAXException;
  21.  
  22. import java.awt.event.*;
  23. import java.io.IOException;
  24.  
  25. /**
  26.  * This is the core of the menusystem, this module should register
  27.  * the Pad-, Ok- and Cancel/back/menu-buttons from remotecontrol.
  28.  * Other submenumodules can register to this module.
  29.  * Submenumodules get (if they need) a row in the root menu.
  30.  * The user navigates the rootmenu with the pad-buttons, when selecting one
  31.  * row with pad-right or ok then this choosen submenu should send its root-menu
  32.  * to menusystem and it sends it to be displayed, menusystem should also
  33.  * send the pad-buttons to this submenu.
  34.  *
  35.  * for now...
  36.  *
  37.  * @author arune
  38.  */
  39. public class modMenuSystem extends MbModule implements ServerDataHandler{
  40.  
  41. private XMLDataHandler flinshDataHandler;
  42. //private XMLParser packetXMLParser;
  43.  
  44. private TcpServer flinshServer;
  45. //private Timer requestDataTimer = null;
  46. //private int timerInterval = 0;
  47. private final char EOF = (char) 0x00;
  48. //A table containing all registered modules (submenus and vlc)
  49. private ArrayList subMenus = new ArrayList();
  50. //what module that should receive all remotebutton changes
  51. private String curButtonReceiver;
  52. //what module that is visible on all flashclients
  53. //often same as curButtonReceiver, but not when curButtonReceiver is vlc-module
  54. private String curSubMenu;
  55.  
  56. private String currentAddress = "";
  57. private int currentLevel = 0;
  58.  
  59. private ArrayList userLogin = new ArrayList();
  60. private ArrayList clientsConnected = new ArrayList();
  61.  
  62. //holds track of what item is marked in the root_menu (menu system)
  63. private String rootMenuMiddleId;
  64.  
  65. private boolean guestCanView;
  66.  
  67. String padUp;
  68. String padDown;
  69. String padLeft;
  70. String padRight;
  71. String padOk;
  72.  
  73.  
  74.     /**
  75.      * Creates a new instance of .
  76.      */
  77.     public modMenuSystem() {
  78.         //construct MbModule
  79.         super();
  80.         //initial values
  81.  
  82.         addDependency("RemoteControl");
  83.        
  84.         //from start the root-menu should be visible
  85.         curButtonReceiver = name();
  86.         curSubMenu = name();
  87.         rootMenuMiddleId = "0";
  88.        
  89.         //subMenuLastMenu = "";
  90.         //register our packet data handler
  91.         setPacketDataHandler(new PacketDataHandler());
  92.         //packetXMLParser = new XMLParser(new PacketDataHandler());
  93.         flinshDataHandler = new FlinshDataHandler();
  94.    }
  95.  
  96.     public String name() {
  97.         return "MenuSystem";
  98.     }
  99.  
  100.     public String description() {
  101.         return "bla";
  102.     }
  103.  
  104.     /**
  105.      * This method sets default values on all _required_ data
  106.      * fields in the data repository.
  107.      */
  108.     public void initDataFields() {
  109.         //set default values on all REQUIRED option fields before starting up subsystems
  110.         //options.putField("mode", "simple");
  111.         //options.putField("checkinterval", "5");
  112.         //options.putField("displaytext", "New mail");
  113. //        options.putField("port", "2050");
  114.     }
  115.  
  116.     public void handleServerData(String data, String address) {
  117.        
  118.         //nulltecken finns, tar bort
  119.         data = data.replaceAll("" + EOF, "");
  120.  
  121.         if (data.length() > 0) {
  122.             if (data.equals("<ping />")) {
  123.                 //gör inget om det är ping
  124.             } else {
  125.                 //_debug.println("got data: " + data);
  126.                
  127.                 //kan vara en säkerhetsrisk att skicka med det såhär, klienten kan ju
  128.                 //konstruera en sån här sträng och skicka till oss
  129.                 //data = "<clientaddress value=\"" + address + "\">" + data;
  130.                 //fet säkerhetsrisk ja
  131.                 //private String currentAddress = "";
  132.                 currentLevel = 0;
  133.                 //check user level
  134.                 currentAddress = address;
  135.                 for (int i=0; i<clientsConnected.size(); i++) {
  136.                     String adr = ((ClientObj)clientsConnected.get(i)).address;
  137.                     if (adr.equals(address)) {
  138.                         currentLevel = ((ClientObj)clientsConnected.get(i)).level;
  139.                         break;
  140.                     }
  141.                 }
  142.                
  143.                
  144.                 //<flinshpacket id="MainMenu" middleitem="1" />
  145.                 if (flinshDataHandler!=null) {
  146.                     //create XML parser and try to parse configuration file
  147.                     XMLParser xmlParser = new XMLParser(flinshDataHandler);
  148.                     try {
  149.                         xmlParser.parseString(data);
  150.                     } catch (SAXException e) {
  151.                         _errors.println("The data send from flinsh contains errors:");
  152.                         _errors.println(e);
  153.                         e.printStackTrace();
  154.                     } catch (IOException e) {
  155.                         //I/O-exception. that's worse, so lets warn
  156.                         _errors.println("I/O-error while trying to read data from flinsh:");
  157.                         _errors.println(e);
  158.                         e.printStackTrace();
  159.                     }
  160.                 }
  161.                 //allt parsas nu av xml-parsern
  162.             }
  163.         }
  164.        
  165.        
  166.     }
  167.    
  168.     /**
  169.      * When a client dropps out, delete it from the client list
  170.      *
  171.      */
  172.     public void clientDropped(String address) {
  173.         for (int i=0; i<clientsConnected.size(); i++) {
  174.             String adr = ((ClientObj)clientsConnected.get(i)).address;
  175.             if (adr.equals(address)) {
  176.                 clientsConnected.remove(i);
  177.                 _debug.println("client dropped: " + address);
  178.                 break;
  179.  
  180.             }
  181.         }
  182.     }
  183.    
  184.     /**
  185.      * When flins client connects it should get the latest menu. If its the root menu  
  186.      * sendRootMenu get called. If its a submenu a refresh is sent to that submenu
  187.      * and the submenu should send out the latest menu to menusystem.
  188.      */
  189.     public void setRemoteAddress(String address) {
  190.         //_debug.println("got connection: " + address);
  191.        
  192.         /*
  193.          * check if the newly connected client has a level specified in config
  194.          */
  195.         int level = 0;
  196.         _debug.println("client connected: " + address);
  197.         //rota igenom listan över de möjliga logins som finns
  198.         for (int i=0; i<userLogin.size(); i++) {
  199.             if (((UserLoginObj)userLogin.get(i)).user.equals("ip")) {
  200.                 String userLoginIp = ((UserLoginObj)userLogin.get(i)).password;
  201.                 String[] ipPort = address.split(":");
  202.                        
  203.                 if (ipPort[0].equals("/" + userLoginIp)) {
  204.                     if (((UserLoginObj)userLogin.get(i)).level > level) {
  205.                         level = ((UserLoginObj)userLogin.get(i)).level;
  206.                         _debug.println("client got level by ip: " + level);
  207.                     }
  208.                 }
  209.             }
  210.         }
  211.         //lägg till klienten i listan över klienter:
  212.         clientsConnected.add(new ClientObj(address, level));
  213.        
  214.         if (curSubMenu.equals(name())) {
  215.             sendRootMenu(address);
  216.         } else {
  217.             sendMacbeth(curSubMenu, "<refresh />");
  218.         }
  219.     }
  220.    
  221.    
  222.     /**
  223.      *
  224.      * @param address Specifies flinsh-client to send data to, send to all clients if null
  225.      */
  226.     private void sendRootMenu(String address) {
  227.         //nu ska vi visa rootmenyn (lista alla submodulers displayname)
  228.         String dataToSend = "<?xml version=\"1.0\"?><packet menuid=\"MainMenu\"><data>";
  229.        
  230.         dataToSend = dataToSend + "<middleid>" + rootMenuMiddleId + "</middleid><list id=\"menudata\">";
  231.         for (int i = 0; i < subMenus.size(); i++) {
  232.             //generera e
  233.             dataToSend = dataToSend + "<item id=\"" + i + "\" title=\"" + ((SubMenu)subMenus.get(i)).getDisplayName() + "\" desc=\"" + ((SubMenu)subMenus.get(i)).getDisplayDesc() + "\" />";
  234.             /*
  235.             dataToSend = dataToSend + "<item>";
  236.             dataToSend = dataToSend + "<id>" + i + "</id>";
  237.             dataToSend = dataToSend + "<title>" + ((SubMenu)subMenus.get(i)).getDisplayName() + "</title>";
  238.             dataToSend = dataToSend + "<description>" + ((SubMenu)subMenus.get(i)).getDisplayDesc() + "</description>";
  239.             dataToSend = dataToSend + "</item>";
  240.             */
  241.         }
  242.         dataToSend = dataToSend + "</list></data></packet>" + EOF;
  243.        
  244.         if (address != null) {
  245.             //skicka till en klient
  246.             if (guestCanView) {
  247.                 flinshServer.sendToClient(dataToSend, address);
  248.             } else {
  249.                 //skicka till alla inloggade med adressen address (level > 0)
  250.                 for (int i=0; i<clientsConnected.size(); i++) {
  251.                     String adr = ((ClientObj)clientsConnected.get(i)).address;
  252.                     int level = ((ClientObj)clientsConnected.get(i)).level;
  253.                     if (adr.equals(address) && level > 0) {
  254.                         flinshServer.sendToClient(dataToSend, adr);
  255.                     }
  256.                 }
  257.             }
  258.                
  259.         } else {
  260.             //skicka till alla
  261.             if (guestCanView) {
  262.                 flinshServer.sendToAll(dataToSend);
  263.             } else {
  264.                 //skicka till alla inloggade (level > 0)
  265.                 for (int i=0; i<clientsConnected.size(); i++) {
  266.                     String adr = ((ClientObj)clientsConnected.get(i)).address;
  267.                     int level = ((ClientObj)clientsConnected.get(i)).level;
  268.                     if (level > 0) {
  269.                         flinshServer.sendToClient(dataToSend, adr);
  270.                     }
  271.                 }
  272.             }
  273.         }
  274.     }
  275.    
  276.     private void sendData(String address, String data) {
  277.         String dataToSend = "<?xml version=\"1.0\"?>";
  278.         dataToSend = dataToSend + data;    
  279.         dataToSend = dataToSend + EOF;
  280.         if (address != null) {
  281.             //skicka till en klient
  282.             flinshServer.sendToClient(dataToSend, address);
  283.         } else {
  284.             //skicka till alla
  285.             if (guestCanView) {
  286.                 flinshServer.sendToAll(dataToSend);
  287.             } else {
  288.                 //skicka till alla inloggade (level > 0)
  289.                 for (int i=0; i<clientsConnected.size(); i++) {
  290.                     String adr = ((ClientObj)clientsConnected.get(i)).address;
  291.                     int level = ((ClientObj)clientsConnected.get(i)).level;
  292.                     if (level > 0) {
  293.                         flinshServer.sendToClient(dataToSend, adr);
  294.                     }
  295.                 }
  296.             }
  297.         }      
  298.     }
  299.    
  300.     private void sendCommand(String address, String command) {
  301.         String dataToSend = "<?xml version=\"1.0\"?><packet menuid=\"MainMenu\"><command>";
  302.         dataToSend = dataToSend + command;
  303.         dataToSend = dataToSend + "</command></packet>" + EOF;
  304.         //_debug.println("skickar " + dataToSend);
  305.         if (address != null) {
  306.             //skicka till en klient
  307.             flinshServer.sendToClient(dataToSend, address);
  308.         } else {
  309.             //skicka till alla
  310.             if (guestCanView) {
  311.                 flinshServer.sendToAll(dataToSend);
  312.             } else {
  313.                 //skicka till alla inloggade (level > 0)
  314.                 for (int i=0; i<clientsConnected.size(); i++) {
  315.                     String adr = ((ClientObj)clientsConnected.get(i)).address;
  316.                     int level = ((ClientObj)clientsConnected.get(i)).level;
  317.                     if (level > 0) {
  318.                         flinshServer.sendToClient(dataToSend, adr);
  319.                     }
  320.                 }
  321.             }
  322.         }
  323.     }
  324.    
  325.     public void startup() throws MbStartupException {
  326.         //startup MbModule
  327.         super.startup();
  328.  
  329.         //get all login users/ip objects from the data repository
  330.         DataRepository.DataList list = dataRepository.getList("login");
  331.         if (list!=null) {
  332.             Iterator it = list.items();
  333.             while (it.hasNext()) {
  334.                 DataRepository.DataListItem item = (DataRepository.DataListItem)it.next();
  335.                 String name = (String)item.getField("user");
  336.                 String passIp = (String)item.getField("pass");
  337.                 int level = 0;
  338.                 try {
  339.                     level = Integer.parseInt((String)item.getField("level"));
  340.                 } catch (NumberFormatException ex) {
  341.                     _errors.println("Config error: level not a number: " + (String)item.getField("level"));
  342.                 }
  343.                
  344.                 userLogin.add(new UserLoginObj(name, passIp, level));
  345.             }
  346.         }
  347.        
  348.         guestCanView = ((String)options.getField("guestcanview")).equals("true");
  349.        
  350.         int flinshServerPort = Integer.parseInt(options.getField("port"));
  351.         //konfigurerbar port via vanlig config
  352.         if (flinshServerPort >= 1024) {
  353.             flinshServer = new TcpServer(flinshServerPort, this);
  354.             flinshServer.startServer();
  355.             flinshServer.setTcpNoDelay(true);
  356.         } else {
  357.             _errors.println("Config error: Port number must be greater than or equal to 1024");
  358.         }
  359.        
  360.         padUp = options.getField("padup");
  361.         padDown = options.getField("paddown");
  362.         padLeft = options.getField("padleft");
  363.         padRight = options.getField("padright");
  364.         padOk = options.getField("padok");
  365.         //lets send requests for their remote control buttons
  366.         MbPacket p = new MbPacket();
  367.         p.setDestination(new MbLocation("self", "RemoteControl"));
  368.         p.appendContents("  <buttonrequest button=\"" + padUp + "\" module=\"" + name() + "\" />");
  369.         p.appendContents("  <buttonrequest button=\"" + padDown + "\" module=\"" + name() + "\" />");
  370.         p.appendContents("  <buttonrequest button=\"" + padLeft + "\" module=\"" + name() + "\" />");
  371.         p.appendContents("  <buttonrequest button=\"" + padRight + "\" module=\"" + name() + "\" />");
  372.         p.appendContents("  <buttonrequest button=\"" + padOk + "\" module=\"" + name() + "\" />");
  373.  
  374.         sendPacket(p);
  375.  
  376.     }
  377.  
  378.     /**
  379.      * Shuts down this module.
  380.      */
  381.     public void shutdown() {
  382.         //stop timer if it's running
  383.         /*if (requestDataTimer!=null) {
  384.             if (requestDataTimer.isRunning()) {
  385.                 requestDataTimer.stop();
  386.             }
  387.         }*/
  388.         //shut down MbModule
  389.         flinshServer.stopServer();
  390.         super.shutdown();
  391.     }
  392.  
  393.     private void sendMacbeth(String receiver, String data) {
  394.         MbPacket p = new MbPacket();
  395.         p.setDestination(new MbLocation("self", receiver));
  396.         p.appendContents(data);
  397.         sendPacket(p);                 
  398.  
  399.     }
  400.    
  401.     private void parseKeys(String button, String state, int level) {
  402.         //_debug.println("knapp " + button + " i state " + state);
  403.         if (state.equals("DOWN")) {
  404.             if (padUp.equals(button)) {
  405.                 //if current button-receiver is the menu system module
  406.                 if (curButtonReceiver.equals(name())) {
  407.                     if (level >= 1) {
  408.                         sendCommand(null, "<scroll>1</scroll>");
  409.                     }
  410.                 } else {
  411.                     sendMacbeth(curButtonReceiver, "<padUp state=\"DOWN\" level=\"" + level + "\" />");
  412.                 }
  413.             }
  414.             else if (padDown.equals(button)) {
  415.                 //if current button-receiver is the menu system module
  416.                 if (curButtonReceiver.equals(name())) {
  417.                     if (level >= 1) {
  418.                         sendCommand(null, "<scroll>-1</scroll>");
  419.                     }
  420.                 } else {
  421.                     sendMacbeth(curButtonReceiver, "<padDown state=\"DOWN\" level=\"" + level + "\" />");
  422.                 }
  423.             }
  424.             else if (padRight.equals(button)) {
  425.                 //if current button-receiver is the menu system module
  426.                 if (curButtonReceiver.equals(name())) {
  427.                     if (level >= 2) {  
  428.                         curButtonReceiver = ((SubMenu)subMenus.get(Integer.parseInt(rootMenuMiddleId))).getModuleName();
  429.                         curSubMenu = curButtonReceiver;
  430.                         sendMacbeth(curSubMenu, "<activate />");
  431.                     }
  432.                 } else {
  433.                     sendMacbeth(curButtonReceiver, "<padRight state=\"DOWN\" level=\"" + level + "\" />");
  434.                 }
  435.             } else if (padLeft.equals(button)) {
  436.                 //if current button-receiver is the menu system module
  437.                 if (curButtonReceiver.equals(name())) {
  438.                     //do nothing
  439.                 } else {
  440.                     sendMacbeth(curButtonReceiver, "<padLeft state=\"DOWN\" level=\"" + level + "\" />");
  441.                 }
  442.             }
  443.  
  444.             else if (padOk.equals(button)) {
  445.                 //if current button-receiver is the menu system module
  446.                 if (curButtonReceiver.equals(name())) {
  447.                    
  448.                 } else {
  449.                     sendMacbeth(curButtonReceiver, "<padOk state=\"DOWN\" level=\"" + level + "\" />");
  450.                 }
  451.             }
  452.         }
  453.         else if (state.equals("UP")) {
  454.             if (padUp.equals(button)) {
  455.                 //if current button-receiver is the menu system module
  456.                 if (curButtonReceiver.equals(name())) {
  457.                     if (level >= 1) {
  458.                         sendCommand(null, "<scroll>0</scroll>");
  459.                     }
  460.                 } else {
  461.                     sendMacbeth(curButtonReceiver, "<padUp state=\"UP\" level=\"" + level + "\" />");
  462.                 }
  463.             }
  464.             else if (padDown.equals(button)) {
  465.                 //if current button-receiver is the menu system module
  466.                 if (curButtonReceiver.equals(name())) {
  467.                     if (level >= 1) {
  468.                         sendCommand(null, "<scroll>0</scroll>");
  469.                     }
  470.                 } else {
  471.                     sendMacbeth(curButtonReceiver, "<padDown state=\"UP\" level=\"" + level + "\" />");
  472.                 }
  473.             }
  474.             else if (padOk.equals(button)) {
  475.                 //if current button-receiver is the menu system module
  476.                 if (curButtonReceiver.equals(name())) {
  477.                    
  478.                 } else {
  479.                     sendMacbeth(curButtonReceiver, "<padOk state=\"UP\" level=\"" + level + "\" />");
  480.                 }
  481.             }
  482.             else if (padLeft.equals(button)) {
  483.                 //if current button-receiver is the menu system module
  484.                 if (curButtonReceiver.equals(name())) {
  485.                    
  486.                 } else {
  487.                     sendMacbeth(curButtonReceiver, "<padLeft state=\"UP\" level=\"" + level + "\" />");
  488.                 }
  489.             }
  490.             else if (padRight.equals(button)) {
  491.                 //if current button-receiver is the menu system module
  492.                 if (curButtonReceiver.equals(name())) {
  493.                    
  494.                 } else {
  495.                     sendMacbeth(curButtonReceiver, "<padRight state=\"UP\" level=\"" + level + "\" />");
  496.                 }
  497.             }
  498.  
  499.         }
  500.     }
  501.  
  502.    
  503.     /**
  504.      * Takes care of XML-data found in incoming macbeth-packets.
  505.      */
  506.     private class PacketDataHandler implements XMLDataHandler {
  507.         public void XMLstartElement(String element, HashMap attributes) {
  508.             if (element.equals("packet")) {
  509.                 if (currentPacket.getSource().getModule().equals(curSubMenu)) {
  510.                     //data arrive from active submenu
  511.                     sendData(null, currentPacket.getContents());
  512.                    
  513.                 } else {
  514.                     //data arrives from submenu that is not active
  515.                     //what happens then?
  516.                 }
  517.                
  518.             } else if (element.equals("deactivates") ) {
  519.                 String module = currentPacket.getSource().getModule();
  520.                 if (curSubMenu.equals(module)) {
  521.                     curSubMenu = name();
  522.                     sendRootMenu(null);
  523.                     sendMacbeth(curSubMenu, "<deactivate />");
  524.                 }
  525.                 if (curButtonReceiver.equals(module)) {
  526.                     curButtonReceiver = name();
  527.                     sendMacbeth(curButtonReceiver, "<deactivate />");
  528.                 }
  529.  
  530.             } else if (element.equals("request") ) {
  531.                 //om en undermeny vill ha uppmärksamhet skickar den "request"
  532.                 //vad är kraven på att en undermeny ska få visas på begäran?
  533.                 //en timeout när vald meny inte skickat något?
  534.                 //eller att en krävd visning kan klickas bort med cancel/back på fjärren
  535.                 // och att man då återgår till den meny som visades innan
  536.                
  537.                 String module = currentPacket.getSource().getModule();
  538.                 if (!curSubMenu.equals(module)) {
  539.                     //kontroller här?
  540.                     curSubMenu = module;
  541.                     sendMacbeth(curSubMenu, "<activate />");
  542.                 }                        
  543.                 if (!curButtonReceiver.equals(module)) {
  544.                     //kontroller här?
  545.                     curButtonReceiver = module;
  546.                 }
  547.  
  548.             /*
  549.              * a submenu should be able to register itself to the menu system
  550.              * it provides a name and description to display, but also a true/false value
  551.              * indicating if the submenu should be displayed in the root_menu list at all
  552.              */
  553.             } else if (element.equals("registersubmod") && attributes.containsKey("displayname") && attributes.containsKey("visible") && attributes.containsKey("displaydesc")) {
  554.                 String displayname = (String)attributes.get("displayname");
  555.                 String displaydesc = (String)attributes.get("displaydesc");
  556.                 _debug.println(displayname + " registrerar sig");
  557.                 //_debug.println(displaydesc);
  558.                 String module = currentPacket.getSource().getModule();
  559.                 boolean visible = false;
  560.                 if (attributes.get("visible").toString().equals("true")) {
  561.                     visible = true;
  562.                 }
  563.  
  564.                 //has this module been reged before?
  565.                 boolean exists = false;
  566.                 for (int i = 0; i < subMenus.size(); i++) {
  567.                     if (((SubMenu)subMenus.get(i)).getModuleName().equals(module)) {
  568.                         exists = true;
  569.                         break;
  570.                     }
  571.                 }
  572.                 if (!exists) {
  573.                     //so create a new submenu object
  574.                     SubMenu sm = new SubMenu(module, displayname, displaydesc, visible);
  575.                     subMenus.add(sm);
  576.                     //refresh flinsh-client menu (if it is root menu)
  577.                     if (curSubMenu.equals(name())) {
  578.                         sendRootMenu(null);
  579.                     }                        
  580.                 }
  581.  
  582.             //en submeny ska kunna avregistrera sig också, om den avslutas
  583.             } else if (element.equals("unregistersubmod") ) {
  584.                 String module = currentPacket.getSource().getModule();
  585.  
  586.                 //has this module been registered?
  587.                 for (int i = 0; i < subMenus.size(); i++) {
  588.                     if (((SubMenu)subMenus.get(i)).getModuleName().equals(module)) {
  589.                         subMenus.remove(i);
  590.                        
  591. //                      TODO: avskaffa parseint på data som kommer utifrån
  592.                         if (Integer.parseInt(rootMenuMiddleId) >= subMenus.size() & Integer.parseInt(rootMenuMiddleId) > 0) {
  593.                             rootMenuMiddleId = "" + (Integer.parseInt(rootMenuMiddleId) - 1);
  594.                         }
  595.                        
  596.                         if (curSubMenu.equals(module)) {
  597.                             curSubMenu = name();
  598.                             //refresha klientens meny (om den är root)
  599.                             sendRootMenu(null);
  600.                         }                        
  601.                         if (curButtonReceiver.equals(module)) {
  602.                             curButtonReceiver = name();
  603.                         }                        
  604.  
  605.                         break;
  606.                     }
  607.                 }
  608.             }
  609.            
  610.             /* Ex: <remotecontrol button="NUMERIC4" state="DOWN" />
  611.              * This is a notification from the remote control module
  612.              * about one of our requested remote control buttons have
  613.              * been pressed. */
  614.             else if (element.equals("remotecontrol") && attributes.containsKey("button") && attributes.containsKey("state")) {
  615.                 String state = (String)attributes.get("state");
  616.                 String button = (String)attributes.get("button");
  617.                 parseKeys(button, state, 3);
  618.             }
  619.            
  620.         }
  621.         public void XMLendElement(String element) {}
  622.         public void XMLelementData(String data) {}
  623.         public void XMLdocumentStart() {}
  624.         public void XMLdocumentEnd() {}
  625.     }
  626.    
  627.     /**
  628.      * Takes care of XML-data found in incoming flinsh-packets.
  629.      */
  630.     private class FlinshDataHandler implements XMLDataHandler {
  631.         public void XMLstartElement(String element, HashMap attributes) {
  632.             if (element.equals("flinshpacket") && attributes.containsKey("button") && attributes.containsKey("state")) {
  633.                 String button = (String)attributes.get("button");
  634.                 String state = (String)attributes.get("state");
  635.                 String newButton = "";
  636.                
  637.                 if (button.equals("padUp")) {
  638.                     newButton = padUp;
  639.                 } else if (button.equals("padDown")) {
  640.                     newButton = padDown;
  641.                 } else if (button.equals("padLeft")) {
  642.                     newButton = padLeft;
  643.                 } else if (button.equals("padRight")) {
  644.                     newButton = padRight;
  645.                 } else if (button.equals("padOk")) {
  646.                     newButton = padOk;
  647.                 }
  648.                
  649.                 if (!newButton.equals("") && (state.equals("UP") || state.equals("DOWN"))) {
  650.                     parseKeys(newButton, state, currentLevel);
  651.                 }
  652.             }
  653.             else if (element.equals("flinshpacket") && attributes.containsKey("menuid") && attributes.containsKey("middleid")) {
  654.                 String id = (String)attributes.get("middleid");
  655.                 String menuid = (String)attributes.get("menuid");
  656.                 //int flinshMiddleItem = Integer.parseInt(id);
  657.                
  658.                 //om root:
  659.                 if (curButtonReceiver.equals(name())) {
  660.                     if (currentLevel >= 2) {
  661.                         rootMenuMiddleId = id;
  662.                     }
  663.                 } else {
  664.                     sendMacbeth(curSubMenu, "<middleid value=\"" + id + "\" menuid=\"" + menuid + "\" userlevel=\"" + currentLevel + "\" />");
  665.                 }
  666.                 //_debug.println("data parsad, id: " + menuid + " middleitem: " + id);
  667.             }
  668.             else if (element.equals("flinshpacket") && attributes.containsKey("login") && attributes.containsKey("pass")) {
  669.                 String user = (String)attributes.get("login");
  670.                 String pass = (String)attributes.get("pass");
  671.                 login(currentAddress, user, pass);
  672.  
  673.             }
  674.  
  675.         }
  676.         public void XMLendElement(String element) {}
  677.         public void XMLelementData(String data) {}
  678.         public void XMLdocumentStart() {}
  679.         public void XMLdocumentEnd() {}
  680.     }
  681.  
  682.     /**
  683.      *
  684.      * @param address
  685.      * @param user
  686.      * @param pass
  687.      */
  688.     private void login(String address, String user, String pass) {
  689.         //ip är inte ett giltigt användarnamn
  690.         //eftersom ip används för att få autologin för ipadresser
  691.         if (!user.equals("ip")) {
  692.             int level = 0;
  693.             //rota igenom listan över de möjliga logins som finns
  694.             for (int i=0; i<userLogin.size(); i++) {
  695.                 String username = ((UserLoginObj)userLogin.get(i)).user;
  696.                 String userLoginIp = ((UserLoginObj)userLogin.get(i)).password;
  697.                 if (username.equals(user) && userLoginIp.equals(pass)) {
  698.                     level = ((UserLoginObj)userLogin.get(i)).level;
  699.                     //rota igenom alla inloggade klienter
  700.                     for (int j=0; j<clientsConnected.size(); j++) {
  701.                         String adr = ((ClientObj)clientsConnected.get(j)).address;
  702.                         if (adr.equals(address)) {
  703.                             int oldlevel = ((ClientObj)clientsConnected.get(j)).level;
  704.                             if (oldlevel < level) {
  705.                                 _debug.println("client logged in with new level: " + level);
  706.                                 ((ClientObj)clientsConnected.get(j)).level = level;
  707.                                 if (oldlevel == 0 && !guestCanView) {
  708.                                     //skicka meny till klienten
  709.                                     if (curSubMenu.equals(name())) {
  710.                                         sendRootMenu(address);
  711.                                     } else {
  712.                                         sendMacbeth(curSubMenu, "<refresh />");
  713.                                     }
  714.                                 }
  715.                             }
  716.                             break;
  717.                         }
  718.                     }
  719.                     break;
  720.                 }
  721.             }  
  722.         }
  723.     }
  724.     /*private class TimerListener implements ActionListener {
  725.  
  726.            public void actionPerformed(ActionEvent e) {
  727.                _debug.println("timer ping");
  728.                //först skicka testdata här bara
  729.                //börja med <scrollup />
  730.                testserver.sendToAll("<?xml version=\"1.0\"?><contentdata><middleitem>0</middleitem><contentname>MainMenu</contentname><list><item><title>08:00 Clifford, den lilla r&#246;da valpen</title><description>Tecknad serie. Del 13 av 17.</description></item><item><title>08:35 Lantmusen och stadsmusen</title><description>Animerad serie. M&#246;ssen Alexander och Emily reser jorden runt. Del 9 av 13.</description></item><item><title>15:00 Perkele</title><description>Test bla bla</description></item></list></contentdata>" + EOF);
  731.                
  732.                //koppla upp sig mot http://www.arune.se/tv/tv_rss_now.php?id0=21&id1=22&id2=26&id3=27&id4=10&id5=42&id6=14&id7=89
  733.                //forma om den xml till det format flinsh vill ha skiten
  734.                //skicka till flinsh
  735.            }
  736.         }*/
  737.  
  738.     /**
  739.      * Objekt som håller reda på vilka möjliga inloggningar klienten kan göra
  740.      */
  741.     private class UserLoginObj {
  742.         public String user;
  743.         public String password;
  744.         public int level;
  745.         /**
  746.          * Creates a new instance of UserLoginObj.
  747.          */
  748.         public UserLoginObj(String user, String password, int level) {
  749.             this.user = user;
  750.             this.password = password;
  751.             this.level = level;
  752.         }
  753.     }
  754.    
  755.     /**
  756.      * Objekt som håller reda på alla inloggade klienter
  757.      * @author arune
  758.      */
  759.     private class ClientObj {
  760.         public String address;
  761.         public int level;
  762.         /**
  763.          * Creates a new instance of ClientObj.
  764.          */
  765.         public ClientObj(String address, int level) {
  766.             this.address = address;
  767.             this.level = level;
  768.         }
  769.     }
  770. }