LayerManagerControl: added support for optional expressions in commands
authorTimo Lotterbach <timo.lotterbach@bmw-carit.de>
Mon, 21 Jan 2013 11:45:41 +0000 (03:45 -0800)
committerTimo Lotterbach <timo.lotterbach@bmw-carit.de>
Tue, 5 Feb 2013 13:59:32 +0000 (05:59 -0800)
optional commands are defined using "[...]" syntax., while variables
are defined using "<...>" syntax.

varibles now additionally may have default values using this syntax:
"get screen <screenid=0>".

Signed-off-by: Timo Lotterbach <timo.lotterbach@bmw-carit.de>
LayerManagerControl/include/Expression.h
LayerManagerControl/src/Expression.cpp
LayerManagerControl/src/ExpressionInterpreter.cpp
LayerManagerControl/src/commands.cpp

index 575d69e..cbe3539 100644 (file)
@@ -37,6 +37,10 @@ public:
     Expression* getPreviousExpression();
     void addNextExpression(Expression* word);
     Expression* getNextExpression(string text);
     Expression* getPreviousExpression();
     void addNextExpression(Expression* word);
     Expression* getNextExpression(string text);
+    ExpressionList getNextExpressions();
+    ExpressionList getClosure(bool bypass);
+    ExpressionList getNextExpressionClosure(string text);
+    ExpressionList getClosureExecutables(bool canBypass);
 
     void setFunc(callback funcPtr);
     void execute();
 
     void setFunc(callback funcPtr);
     void execute();
@@ -51,6 +55,7 @@ public:
     int getInt(string name);
     double getDouble(string name);
     bool getBool(string name);
     int getInt(string name);
     double getDouble(string name);
     bool getBool(string name);
+    bool contains(string name);
 
     void printTree(int level = 0);
     void printList(string list = "");
 
     void printTree(int level = 0);
     void printList(string list = "");
@@ -61,6 +66,7 @@ private:
     Expression* mPreviousWord;
     callback mFuncPtr;
     string mVarValue;
     Expression* mPreviousWord;
     callback mFuncPtr;
     string mVarValue;
+    string mMatchText;
 
 };
 
 
 };
 
index 7dd8500..aa4219c 100644 (file)
 #include <sstream>
 #include <stdio.h>
 #include <string.h>  // memcpy
 #include <sstream>
 #include <stdio.h>
 #include <string.h>  // memcpy
+#include <algorithm>
 
 Expression::Expression(string name, Expression* parent)
 : mName(name)
 , mPreviousWord(parent)
 , mFuncPtr(NULL)
 
 Expression::Expression(string name, Expression* parent)
 : mName(name)
 , mPreviousWord(parent)
 , mFuncPtr(NULL)
+, mMatchText("")
 {
 }
 
 {
 }
 
@@ -36,28 +38,41 @@ void Expression::setVarValue(string value)
 
 bool Expression::isVar()
 {
 
 bool Expression::isVar()
 {
-    return mName[0] == '<';
+    return mName[0] == '<' || (mName[0] == '[' && mName[1] == '<');
 }
 
 string Expression::getString(string name)
 {
 }
 
 string Expression::getString(string name)
 {
-    string varName;
-    varName += "<";
-    varName += name;
-    varName += ">";
+    //remove brackets if needed
+    string noBrackets = mName;
+    noBrackets = noBrackets[0] == '['? noBrackets.substr(1, noBrackets.size()-1) : noBrackets;
+    noBrackets = noBrackets[noBrackets.size()-1] == ']'? noBrackets.substr(0, noBrackets.size()-1) : noBrackets;
 
 
-    if (mName != varName)
+    noBrackets = noBrackets[0] == '<'? noBrackets.substr(1, noBrackets.size()-1) : noBrackets;
+    noBrackets = noBrackets[noBrackets.size()-1] == '>'? noBrackets.substr(0, noBrackets.size()-1) : noBrackets;
+
+    //remove default value (if needed)
+    string exprName = noBrackets.substr(0, noBrackets.find("="));
+
+    if (exprName == name)
     {
     {
-        if (mPreviousWord)
+        if (mMatchText != "")
         {
         {
-            return mPreviousWord->getString(name);
+            //if there was a match return the value
+            return mVarValue;
         }
         }
-        else
+        else if (noBrackets.find("=") != string::npos)
         {
         {
-            return "";
+            //return default value
+            return noBrackets.substr(noBrackets.find("=") + 1);
         }
     }
         }
     }
-    return mVarValue;
+    else if (mPreviousWord)
+    {
+        return mPreviousWord->getString(name);
+    }
+
+    return "";
 }
 
 unsigned int Expression::getUint(string name)
 }
 
 unsigned int Expression::getUint(string name)
@@ -128,6 +143,11 @@ bool Expression::getBool(string name)
     return sscanf(stringVal.c_str(), "%d", &value) && value;
 }
 
     return sscanf(stringVal.c_str(), "%d", &value) && value;
 }
 
+bool Expression::contains(string name)
+{
+    return mMatchText == name || (mPreviousWord && mPreviousWord->contains(name));
+}
+
 string Expression::getName()
 {
     return mName;
 string Expression::getName()
 {
     return mName;
@@ -144,6 +164,111 @@ void Expression::addNextExpression(Expression* word)
     mNextWords.sort(ExpressionCompare);
 }
 
     mNextWords.sort(ExpressionCompare);
 }
 
+ExpressionList Expression::getClosure(bool bypass)
+{
+    ExpressionList closure;
+
+    if(bypass)
+    {
+        //if expression is end of the optional expression
+        bool bypassChildren = mName[mName.length() - 1] != ']';
+        //get closure of children
+        ExpressionList::const_iterator iter = mNextWords.begin();
+        ExpressionList::const_iterator end = mNextWords.end();
+        for (; iter != end; ++iter)
+        {
+            ExpressionList childClosure = (*iter)->getClosure(bypassChildren);
+            closure.splice(closure.end(), childClosure);
+        }
+    }
+    else
+    {
+        closure.push_back(this);
+        //if start of optional expression
+        if (mName[0] == '[')
+        {
+            //get closure of elements after the end of the expression
+            ExpressionList restClosure = getClosure(true);
+            closure.splice(closure.end(), restClosure);
+        }
+    }
+
+    return closure;
+}
+
+ExpressionList Expression::getNextExpressionClosure(string text)
+{
+    ExpressionList nextClosure;
+
+    ExpressionList::const_iterator iter = mNextWords.begin();
+    ExpressionList::const_iterator end = mNextWords.end();
+    for (; iter != end; ++iter)
+    {
+        Expression* childExpr = *iter;
+        ExpressionList childClosure = childExpr->getClosure(false);
+
+        ExpressionList::const_iterator iter = childClosure.begin();
+        ExpressionList::const_iterator end = childClosure.end();
+        for (; iter != end; ++iter)
+        {
+            Expression* expr = *iter;
+
+            if (expr->isVar())
+            {
+                nextClosure.push_back(expr);
+
+                expr->setVarValue(text);
+
+                string exprName = expr->mName;
+
+                //remove brakcets
+                exprName = exprName[0] == '['? exprName.substr(1, exprName.size()-1) : exprName;
+                exprName = exprName[exprName.size()-1] == ']'? exprName.substr(0, exprName.size()-1) : exprName;
+
+                exprName = exprName[0] == '<'? exprName.substr(1, exprName.size()-1) : exprName;
+                exprName = exprName[exprName.size()-1] == '>'? exprName.substr(0, exprName.size()-1) : exprName;
+
+                //remove default value (if needed)
+                exprName = exprName.substr(0, exprName.find("="));
+
+                expr->mMatchText = exprName;
+            }
+            else
+            {
+                //remove brackets if needed
+                string exprName = expr->mName;
+                exprName = exprName[0] == '['? exprName.substr(1, exprName.size()-1) : exprName;
+                exprName = exprName[exprName.size()-1] == ']'? exprName.substr(0, exprName.size()-1) : exprName;
+
+                //check all alternatives (in case there are alternatives)
+                while (exprName.length() > 0)
+                {
+                    //get next part
+                    string temp = exprName.substr(0, exprName.find("|", 1));
+                    exprName = exprName.substr(temp.length());
+
+                    //it there is a '|' at beginning remove it
+                    temp = temp[0] == '|' ? temp.substr(1) : temp;
+                    if (temp == text)
+                    {
+                        //add to result !
+                        nextClosure.push_back(expr);
+                        expr->mMatchText = text;
+                        break; //from inner loop !
+                    }
+                }
+            }
+        }
+    }
+
+    return nextClosure;
+}
+
+ExpressionList Expression::getNextExpressions()
+{
+    return this->mNextWords;
+}
+
 Expression* Expression::getNextExpression(string text)
 {
     Expression* varMatch = NULL;
 Expression* Expression::getNextExpression(string text)
 {
     Expression* varMatch = NULL;
@@ -154,8 +279,9 @@ Expression* Expression::getNextExpression(string text)
     for (; iter != end; ++iter)
     {
         Expression* expr = *iter;
     for (; iter != end; ++iter)
     {
         Expression* expr = *iter;
+        string exprName = expr->getName();
 
 
-        if (expr->getName() == text)
+        if (exprName == text)
         {
             nameMatch = expr;
         }
         {
             nameMatch = expr;
         }
@@ -170,6 +296,73 @@ Expression* Expression::getNextExpression(string text)
     return nameMatch ? nameMatch : (varMatch ? varMatch : NULL);
 }
 
     return nameMatch ? nameMatch : (varMatch ? varMatch : NULL);
 }
 
+ExpressionList Expression::getClosureExecutables(bool canBypass)
+{
+    ExpressionList candidateExecutables;
+
+    if (canBypass)
+    {
+        string expName = this->mName;
+        if (mName[mName.length() - 1] == ']')
+        {
+            //as if this child was the "last consumed" expression by the user string input !
+            ExpressionList childExecutables = getClosureExecutables(false);
+            candidateExecutables.splice(candidateExecutables.end(), childExecutables);
+        }
+        else
+        {
+            ExpressionList::const_iterator iter = mNextWords.begin();
+            ExpressionList::const_iterator end = mNextWords.end();
+            for (; iter != end; ++iter)
+            {
+                string childName = (*iter)->mName;
+
+                ExpressionList childClosure = (*iter)->getClosureExecutables(true);
+                candidateExecutables.splice(candidateExecutables.end(), childClosure);
+            }
+        }
+    }
+    else
+    {
+        //add myself to candidate executables
+        candidateExecutables.push_back(this);
+
+        //get candidate executables from children
+        ExpressionList::const_iterator iter = mNextWords.begin();
+        ExpressionList::const_iterator end = mNextWords.end();
+        for (; iter != end; ++iter)
+        {
+            //if child is start of optional expression: get executable closure from the ends of this child
+            string childName = (*iter)->mName;
+            if (childName[0] == '[')
+            {
+                ExpressionList childClosure = (*iter)->getClosureExecutables(true);
+                candidateExecutables.splice(candidateExecutables.end(), childClosure);
+            }
+        }
+    }
+
+    //return only the executable expressions
+    ExpressionList executables;
+
+    ExpressionList::const_iterator iter = candidateExecutables.begin();
+    ExpressionList::const_iterator end = candidateExecutables.end();
+    for (; iter != end; ++iter)
+    {
+        Expression* expr = *iter;
+
+        //check if it already exists in the list
+        bool duplicate = std::find(executables.begin(), executables.end(), expr) != executables.end();
+
+        if ((! duplicate) && expr->isExecutable())
+        {
+            executables.push_back(expr);
+        }
+    }
+
+    return executables;
+}
+
 void Expression::printTree(int level)
 {
     for (int i = 0; i < level; ++i)
 void Expression::printTree(int level)
 {
     for (int i = 0; i < level; ++i)
index e8c9850..3a2215b 100644 (file)
@@ -24,6 +24,8 @@
 #include <algorithm> // transform
 #include <ctype.h> // tolower
 
 #include <algorithm> // transform
 #include <ctype.h> // tolower
 
+#include <iostream>
+
 Expression* ExpressionInterpreter::mpRoot = NULL;
 
 ExpressionInterpreter::ExpressionInterpreter()
 Expression* ExpressionInterpreter::mpRoot = NULL;
 
 ExpressionInterpreter::ExpressionInterpreter()
@@ -50,7 +52,6 @@ bool ExpressionInterpreter::addExpression(callback funcPtr, string command)
     {
         ss >> text;
         transform(text.begin(), text.end(), text.begin(), ::tolower);
     {
         ss >> text;
         transform(text.begin(), text.end(), text.begin(), ::tolower);
-        string name = currentWord->getName();
 
         Expression* nextWord = currentWord->getNextExpression(text);
 
 
         Expression* nextWord = currentWord->getNextExpression(text);
 
@@ -75,18 +76,28 @@ CommandResult ExpressionInterpreter::interpretCommand(string userInput)
     stringstream ss;
     ss << userInput;
 
     stringstream ss;
     ss << userInput;
 
-    Expression* currentWord = mpRoot;
+    ExpressionList currentState;
+    currentState.push_back(mpRoot);
+    ExpressionList nextState;
 
     while (result == CommandSuccess && !ss.eof())
     {
         ss >> text;
         transform(text.begin(), text.end(), text.begin(), ::tolower);
 
 
     while (result == CommandSuccess && !ss.eof())
     {
         ss >> text;
         transform(text.begin(), text.end(), text.begin(), ::tolower);
 
-        Expression* nextWord = currentWord->getNextExpression(text);
+        ExpressionList::const_iterator iter = currentState.begin();
+        ExpressionList::const_iterator end = currentState.end();
+        for (;iter != end; ++iter)
+        {
+            Expression* expr = *iter;
+            ExpressionList exprNextList = expr->getNextExpressionClosure(text);
+            nextState.splice(nextState.end(), exprNextList);
+        }
 
 
-        if (nextWord)
+        if (nextState.size() > 0)
         {
         {
-            currentWord = nextWord;
+            currentState = nextState;
+            nextState.clear();
         }
         else
         {
         }
         else
         {
@@ -95,28 +106,80 @@ CommandResult ExpressionInterpreter::interpretCommand(string userInput)
         }
     }
 
         }
     }
 
+    //remove impossible expressions in the final state before checking for ambiguity
+    nextState.clear();
+    ExpressionList::const_iterator iter = currentState.begin();
+    ExpressionList::const_iterator end = currentState.end();
+    for (;iter != end; ++iter)
+    {
+        Expression* expr = *iter;
+        if (expr->isExecutable())
+        {
+            nextState.push_back(expr);
+        }
+        else
+        {
+            ExpressionList children = expr->getNextExpressions();
+
+            bool flag = false;
+
+            ExpressionList::const_iterator iter = children.begin();
+            ExpressionList::const_iterator end = children.end();
+            for (;iter != end; ++iter)
+            {
+                if ((*iter)->getName()[0] == '[')
+                {
+                    flag = true;
+                }
+            }
+
+            if (flag || children.size() == 0)
+            {
+                nextState.push_back(expr);
+            }
+        }
+    }
+
+    currentState = nextState;
+
+    if (currentState.size() != 1)
+    {
+        mErrorText = "'" + text + "' ambiguous or incomplete.";
+        result = CommandInvalid;
+    }
+
+    //run command if executable and non-ambiguous
     if (result == CommandSuccess)
     {
     if (result == CommandSuccess)
     {
-        if (currentWord->isExecutable())
+        Expression* expr = *(currentState.begin());
+
+        ExpressionList executables = expr->getClosureExecutables(false);
+        if (executables.size() == 1)
         {
             if (ILM_SUCCESS != ilm_init())
             {
                 mErrorText = "Could not connect to LayerManagerService.";
                 result = CommandExecutionFailed;
             }
         {
             if (ILM_SUCCESS != ilm_init())
             {
                 mErrorText = "Could not connect to LayerManagerService.";
                 result = CommandExecutionFailed;
             }
-
             else
             {
             else
             {
-                currentWord->execute();
+                Expression* exec = executables.front();
+                exec->execute();
                 ilm_destroy();
             }
         }
                 ilm_destroy();
             }
         }
-        else
+        else if (executables.size() == 0)
         {
             mErrorText = "command is incomplete.";
             result = CommandIncomplete;
         }
         {
             mErrorText = "command is incomplete.";
             result = CommandIncomplete;
         }
+        else
+        {
+            mErrorText = "command is ambiguous.";
+            result = CommandIncomplete;
+        }
     }
     }
+
     return result;
 }
 
     return result;
 }
 
index b6c09b9..c792fc7 100644 (file)
@@ -67,315 +67,311 @@ COMMAND("tree")
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("get screens")
+COMMAND("get scene|screens|layers|surfaces")
 //=============================================================================
 {
 //=============================================================================
 {
-    (void)input;
-    unsigned int count = 0;
-    unsigned int* array = NULL;
-    ilm_getScreenIDs(&count, &array);
-    printArray("Screen", array, count);
-}
-
-//=============================================================================
-COMMAND("get layers")
-//=============================================================================
-{
-    (void)input;
-    int count = 0;
-    unsigned int* array = NULL;
-    ilm_getLayerIDs(&count, &array);
-    printArray("Layer", array, count);
-}
-
-//=============================================================================
-COMMAND("get surfaces")
-//=============================================================================
-{
-    (void)input;
-    int count = 0;
-    unsigned int* array = NULL;
-    ilm_getSurfaceIDs(&count, &array);
-    printArray("Surface", array, count);
-}
-
-//=============================================================================
-COMMAND("get screen <screenid>")
-//=============================================================================
-{
-    printScreenProperties(input->getUint("screenid"));
-}
-
-//=============================================================================
-COMMAND("get layer <layerid>")
-//=============================================================================
-{
-    printLayerProperties(input->getUint("layerid"));
-}
-
-//=============================================================================
-COMMAND("get surface <surfaceid>")
-//=============================================================================
-{
-    printSurfaceProperties(input->getUint("surfaceid"));
-}
-
-//=============================================================================
-COMMAND("dump screen <screenid> to <file>")
-//=============================================================================
-{
-    ilm_takeScreenshot(input->getUint("screenid"),
-                       input->getString("file").c_str());
-}
-
-//=============================================================================
-COMMAND("dump layer <layerid> to <file>")
-//=============================================================================
-{
-    ilm_takeLayerScreenshot(input->getString("file").c_str(),
-                            input->getUint("layerid"));
-}
-
-//=============================================================================
-COMMAND("dump surface <surfaceid> to <file>")
-//=============================================================================
-{
-    ilm_takeSurfaceScreenshot(input->getString("file").c_str(),
-                              input->getUint("surfaceid"));
-}
-
-//=============================================================================
-COMMAND("set layer <layerid> source region <x> <y> <w> <h>")
-//=============================================================================
-{
-    ilm_layerSetSourceRectangle(input->getUint("layerid"),
-                                input->getUint("x"),
-                                input->getUint("y"),
-                                input->getUint("w"),
-                                input->getUint("h"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set surface <surfaceid> source region <x> <y> <w> <h>")
-//=============================================================================
-{
-    ilm_surfaceSetSourceRectangle(input->getUint("surfaceid"),
-                                  input->getUint("x"),
-                                  input->getUint("y"),
-                                  input->getUint("w"),
-                                  input->getUint("h"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set layer <layerid> destination region <x> <y> <w> <h>")
-//=============================================================================
-{
-    ilm_layerSetDestinationRectangle(input->getUint("layerid"),
-                                     input->getUint("x"),
-                                     input->getUint("y"),
-                                     input->getUint("w"),
-                                     input->getUint("h"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set surface <surfaceid> destination region <x> <y> <w> <h>")
-//=============================================================================
-{
-    ilm_surfaceSetDestinationRectangle(input->getUint("surfaceid"),
-                                       input->getUint("x"),
-                                       input->getUint("y"),
-                                       input->getUint("w"),
-                                       input->getUint("h"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set layer <layerid> opacity <opacity>")
-//=============================================================================
-{
-    ilm_layerSetOpacity(input->getUint("layerid"),
-                        input->getDouble("opacity"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set surface <surfaceid> opacity <opacity>")
-//=============================================================================
-{
-    ilm_surfaceSetOpacity(input->getUint("surfaceid"),
-                          input->getDouble("opacity"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set layer <layerid> visibility <visibility>")
-//=============================================================================
-{
-    ilm_layerSetVisibility(input->getUint("layerid"),
-                           input->getBool("visibility"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set surface <surfaceid> visibility <visibility>")
-//=============================================================================
-{
-    ilm_surfaceSetVisibility(input->getUint("surfaceid"),
-                             input->getBool("visibility"));
-    ilm_commitChanges();
-}
-
-//=============================================================================
-COMMAND("set layer <layerid> orientation <orientation>")
-//=============================================================================
-{
-    ilm_layerSetOrientation(input->getUint("layerid"),
-            (ilmOrientation)input->getInt("orientation"));
-    ilm_commitChanges();
+    if (input->contains("scene"))
+    {
+        printScene();
+    }
+    else if (input->contains("screens"))
+    {
+        (void)input;
+        unsigned int count = 0;
+        unsigned int* array = NULL;
+        ilm_getScreenIDs(&count, &array);
+        printArray("Screen", array, count);
+    }
+    else if (input->contains("layers"))
+    {
+        (void)input;
+        int count = 0;
+        unsigned int* array = NULL;
+        ilm_getLayerIDs(&count, &array);
+        printArray("Layer", array, count);
+    }
+    else if (input->contains("surfaces"))
+    {
+        (void)input;
+        int count = 0;
+        unsigned int* array = NULL;
+        ilm_getSurfaceIDs(&count, &array);
+        printArray("Surface", array, count);
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set surface <surfaceid> orientation <orientation>")
+COMMAND("get screen|layer|surface <id>")
 //=============================================================================
 {
 //=============================================================================
 {
-    ilm_surfaceSetOrientation(input->getUint("surfaceid"),
-              (ilmOrientation)input->getInt("orientation"));
-    ilm_commitChanges();
+    if (input->contains("screen"))
+    {
+        printScreenProperties(input->getUint("id"));
+    }
+    else if (input->contains("layer"))
+    {
+        printLayerProperties(input->getUint("id"));
+    }
+    else if (input->contains("surface"))
+    {
+        printSurfaceProperties(input->getUint("id"));
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set screen <screenid> render order <layeridarray>")
+COMMAND("dump screen|layer|surface <id> to <file>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int count = 0;
-    unsigned int* array = NULL;
-    unsigned int screenid = input->getUint("screenid");
-    input->getUintArray("layeridarray", &array, &count);
-    ilm_displaySetRenderOrder(screenid, array, count);
-    ilm_commitChanges();
+    if (input->contains("screen"))
+    {
+        ilm_takeScreenshot(input->getUint("id"),
+                           input->getString("file").c_str());
+    }
+    else if (input->contains("layer"))
+    {
+        ilm_takeLayerScreenshot(input->getString("file").c_str(),
+                                input->getUint("id"));
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_takeSurfaceScreenshot(input->getString("file").c_str(),
+                                  input->getUint("id"));
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set screen <screenid> render order")
+COMMAND("set layer|surface <id> source region <x> <y> <w> <h>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int screenid = input->getUint("screenid");
-    ilm_displaySetRenderOrder(screenid, NULL, 0);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        ilm_layerSetSourceRectangle(input->getUint("id"),
+                                    input->getUint("x"),
+                                    input->getUint("y"),
+                                    input->getUint("w"),
+                                    input->getUint("h"));
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_surfaceSetSourceRectangle(input->getUint("id"),
+                                      input->getUint("x"),
+                                      input->getUint("y"),
+                                      input->getUint("w"),
+                                      input->getUint("h"));
+            ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set layer <layerid> render order <surfaceidarray>")
+COMMAND("set layer|surface <id> destination region <x> <y> <w> <h>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int count = 0;
-    unsigned int* array = NULL;
-    unsigned int layerid = input->getUint("layerid");
-    input->getUintArray("surfaceidarray", &array, &count);
-    ilm_layerSetRenderOrder(layerid, array, count);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        ilm_layerSetDestinationRectangle(input->getUint("id"),
+                                        input->getUint("x"),
+                                        input->getUint("y"),
+                                        input->getUint("w"),
+                                        input->getUint("h"));
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_surfaceSetDestinationRectangle(input->getUint("id"),
+                                           input->getUint("x"),
+                                           input->getUint("y"),
+                                           input->getUint("w"),
+                                           input->getUint("h"));
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set layer <layerid> render order")
+COMMAND("set layer|surface <id> opacity <opacity>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int layerid = input->getUint("layerid");
-    ilm_layerSetRenderOrder(layerid, NULL, 0);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        ilm_layerSetOpacity(input->getUint("id"),
+                input->getDouble("opacity"));
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_surfaceSetOpacity(input->getUint("id"),
+                                  input->getDouble("opacity"));
+            ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set layer <layerid> width <width>")
+COMMAND("set layer|surface <id> visibility <visibility>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int dimension[2];
-    unsigned int layerid = input->getUint("layerid");
-    ilm_layerGetDimension(layerid, dimension);
-    dimension[0] = input->getUint("width");
-    ilm_layerSetDimension(layerid, dimension);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        ilm_layerSetVisibility(input->getUint("id"),
+                               input->getBool("visibility"));
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_surfaceSetVisibility(input->getUint("id"),
+                                 input->getBool("visibility"));
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set surface <surfaceid> width <width>")
+COMMAND("set layer|surface <id> orientation <orientation>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int dimension[2];
-    unsigned int surfaceid = input->getUint("surfaceid");
-    ilm_surfaceGetDimension(surfaceid, dimension);
-    dimension[0] = input->getUint("width");
-    ilm_surfaceSetDimension(surfaceid, dimension);
-    ilm_commitChanges();
-}
+    if (input->contains("layer"))
+    {
+        ilm_layerSetOrientation(input->getUint("id"),
+                    (ilmOrientation)input->getInt("orientation"));
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        ilm_surfaceSetOrientation(input->getUint("id"),
+                      (ilmOrientation)input->getInt("orientation"));
+        ilm_commitChanges();
+    }
 
 
-//=============================================================================
-COMMAND("set layer <layerid> height <height>")
-//=============================================================================
-{
-    unsigned int dimension[2];
-    unsigned int layerid = input->getUint("layerid");
-    ilm_layerGetDimension(layerid, dimension);
-    dimension[1] = input->getUint("height");
-    ilm_layerSetDimension(layerid, dimension);
-    ilm_commitChanges();
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set surface <surfaceid> height <height>")
+COMMAND("set screen|layer <id> render order [<idarray>]")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int dimension[2];
-    unsigned int surfaceid = input->getUint("surfaceid");
-    ilm_surfaceGetDimension(surfaceid, dimension);
-    dimension[1] = input->getUint("height");
-    ilm_surfaceSetDimension(surfaceid, dimension);
-    ilm_commitChanges();
+    if (input->contains("screen"))
+    {
+        if (input->contains("idarray"))
+        {
+            unsigned int count = 0;
+            unsigned int* array = NULL;
+            unsigned int screenid = input->getUint("id");
+            input->getUintArray("idarray", &array, &count);
+            ilm_displaySetRenderOrder(screenid, array, count);
+            ilm_commitChanges();
+        }
+        else
+        {
+            unsigned int screenid = input->getUint("id");
+            ilm_displaySetRenderOrder(screenid, NULL, 0);
+            ilm_commitChanges();
+        }
+    }
+    else if (input->contains("layer"))
+    {
+        if (input->contains("idarray"))
+        {
+            unsigned int count = 0;
+            unsigned int* array = NULL;
+            unsigned int layerid = input->getUint("id");
+            input->getUintArray("idarray", &array, &count);
+            ilm_layerSetRenderOrder(layerid, array, count);
+            ilm_commitChanges();
+        }
+        else
+        {
+            unsigned int layerid = input->getUint("id");
+            ilm_layerSetRenderOrder(layerid, NULL, 0);
+            ilm_commitChanges();
+        }
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set layer <layerid> position <x> <y>")
+COMMAND("set layer|surface <id> width <width>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int dimension[2];
-    unsigned int layerid = input->getUint("layerid");
-    dimension[0] = input->getUint("x");
-    dimension[1] = input->getUint("y");
-    ilm_layerSetPosition(layerid, dimension);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        unsigned int dimension[2];
+        unsigned int layerid = input->getUint("id");
+        ilm_layerGetDimension(layerid, dimension);
+        dimension[0] = input->getUint("width");
+        ilm_layerSetDimension(layerid, dimension);
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        unsigned int dimension[2];
+        unsigned int surfaceid = input->getUint("id");
+        ilm_surfaceGetDimension(surfaceid, dimension);
+        dimension[0] = input->getUint("width");
+        ilm_surfaceSetDimension(surfaceid, dimension);
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set surface <surfaceid> position <x> <y>")
+COMMAND("set layer|surface <id> height <height>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int dimension[2];
-    unsigned int surfaceid = input->getUint("surfaceid");
-    dimension[0] = input->getUint("x");
-    dimension[1] = input->getUint("y");
-    ilm_surfaceSetPosition(surfaceid, dimension);
-    ilm_commitChanges();
+    if (input->contains("layer"))
+    {
+        unsigned int dimension[2];
+        unsigned int layerid = input->getUint("id");
+        ilm_layerGetDimension(layerid, dimension);
+        dimension[1] = input->getUint("height");
+        ilm_layerSetDimension(layerid, dimension);
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        unsigned int dimension[2];
+        unsigned int surfaceid = input->getUint("id");
+        ilm_surfaceGetDimension(surfaceid, dimension);
+        dimension[1] = input->getUint("height");
+        ilm_surfaceSetDimension(surfaceid, dimension);
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("create layer <layerid>")
+COMMAND("set layer|surface <id> position <x> <y>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int layerid = input->getUint("layerid");
-    ilm_layerCreate(&layerid);
+    if (input->contains("layer"))
+    {
+        unsigned int dimension[2];
+        unsigned int layerid = input->getUint("id");
+        dimension[0] = input->getUint("x");
+        dimension[1] = input->getUint("y");
+        ilm_layerSetPosition(layerid, dimension);
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        unsigned int dimension[2];
+        unsigned int surfaceid = input->getUint("id");
+        dimension[0] = input->getUint("x");
+        dimension[1] = input->getUint("y");
+        ilm_surfaceSetPosition(surfaceid, dimension);
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("create layer <layerid> <width> <height>")
+COMMAND("create layer <layerid> [<width> <height>]")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int layerid = input->getUint("layerid");
-    unsigned int width = input->getUint("width");
-    unsigned int height = input->getUint("height");
-    ilm_layerCreateWithDimension(&layerid, width, height);
+    if (input->contains("width") && input->contains("height"))
+    {
+        unsigned int layerid = input->getUint("layerid");
+        unsigned int width = input->getUint("width");
+        unsigned int height = input->getUint("height");
+        ilm_layerCreateWithDimension(&layerid, width, height);
+    }
+    else
+    {
+        unsigned int layerid = input->getUint("layerid");
+        ilm_layerCreate(&layerid);
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
@@ -391,27 +387,19 @@ COMMAND("create surface <surfaceid> <nativehandle> <width> <height> <pixelformat
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("destroy layer <layerid>")
-//=============================================================================
-{
-    unsigned int layerid = input->getUint("layerid");
-    ilm_layerRemove(layerid);
-}
-
-//=============================================================================
-COMMAND("destroy surface <surfaceid>")
+COMMAND("destroy layer|surface <id>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int surfaceid = input->getUint("surfaceid");
-    ilm_surfaceRemove(surfaceid);
-}
-
-//=============================================================================
-COMMAND("get scene")
-//=============================================================================
-{
-    (void) input; //suppress warning: unused parameter
-    printScene();
+    if (input->contains("layer"))
+    {
+        unsigned int layerid = input->getUint("id");
+        ilm_layerRemove(layerid);
+    }
+    else if (input->contains("surface"))
+    {
+        unsigned int surfaceid = input->getUint("id");
+        ilm_surfaceRemove(surfaceid);
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
@@ -451,18 +439,34 @@ COMMAND("set surface <surfaceid> accept <acceptance> input events from devices <
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set surface <surfaceid> chromakey <red> <green> <blue>")
+COMMAND("set layer|surface <id> chromakey <red> <green> <blue>")
 //=============================================================================
 {
 //=============================================================================
 {
-    t_ilm_surface surface = input->getUint("surfaceid");
-    t_ilm_int color[3] =
+    if (input->contains("layer"))
     {
     {
-        input->getInt("red"),
-        input->getInt("green"),
-        input->getInt("blue")
-    };
-    ilm_surfaceSetChromaKey(surface, color);
-    ilm_commitChanges();
+        t_ilm_layer layer = input->getUint("id");
+        t_ilm_int color[3] =
+        {
+            input->getInt("red"),
+            input->getInt("green"),
+            input->getInt("blue")
+        };
+
+        ilm_layerSetChromaKey(layer, color);
+        ilm_commitChanges();
+    }
+    else if (input->contains("surface"))
+    {
+        t_ilm_surface surface = input->getUint("id");
+        t_ilm_int color[3] =
+        {
+            input->getInt("red"),
+            input->getInt("green"),
+            input->getInt("blue")
+        };
+        ilm_surfaceSetChromaKey(surface, color);
+        ilm_commitChanges();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
@@ -475,22 +479,6 @@ COMMAND("set surface <surfaceid> chromakey disabled")
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("set layer <layerid> chromakey <red> <green> <blue>")
-//=============================================================================
-{
-    t_ilm_surface surface = input->getUint("layerid");
-    t_ilm_int color[3] =
-    {
-        input->getInt("red"),
-        input->getInt("green"),
-        input->getInt("blue")
-    };
-
-    ilm_layerSetChromaKey(surface, color);
-    ilm_commitChanges();
-}
-
-//=============================================================================
 COMMAND("test notification layer <layerid>")
 //=============================================================================
 {
 COMMAND("test notification layer <layerid>")
 //=============================================================================
 {
@@ -500,25 +488,25 @@ COMMAND("test notification layer <layerid>")
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("watch layer <layeridarray>")
+COMMAND("watch layer|surface <idarray>")
 //=============================================================================
 {
 //=============================================================================
 {
-    unsigned int* layerids = NULL;
-    unsigned int layeridCount;
-    input->getUintArray("layeridarray", &layerids, &layeridCount);
-
-    watchLayer(layerids, layeridCount);
-}
+    if (input->contains("layer"))
+    {
+        unsigned int* layerids = NULL;
+        unsigned int layeridCount;
+        input->getUintArray("idarray", &layerids, &layeridCount);
 
 
-//=============================================================================
-COMMAND("watch surface <surfaceidarray>")
-//=============================================================================
-{
-    unsigned int* surfaceids = NULL;
-    unsigned int surfaceidCount;
-    input->getUintArray("surfaceidarray", &surfaceids, &surfaceidCount);
+        watchLayer(layerids, layeridCount);
+    }
+    else if (input->contains("surface"))
+    {
+        unsigned int* surfaceids = NULL;
+        unsigned int surfaceidCount;
+        input->getUintArray("idarray", &surfaceids, &surfaceidCount);
 
 
-    watchSurface(surfaceids, surfaceidCount);
+        watchSurface(surfaceids, surfaceidCount);
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
@@ -547,23 +535,21 @@ COMMAND("analyze surface <surfaceid>")
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("scatter")
-//=============================================================================
-{
-    (void) input; //suppress warning: unused parameter
-    scatter();
-}
-
-//=============================================================================
-COMMAND("scatter all")
+COMMAND("scatter [all]")
 //=============================================================================
 {
 //=============================================================================
 {
-    (void) input; //suppress warning: unused parameter
-    scatterAll();
+    if (input->contains("all"))
+    {
+        scatterAll();
+    }
+    else
+    {
+        scatter();
+    }
 }
 
 //=============================================================================
 }
 
 //=============================================================================
-COMMAND("demo <animation_mode>")
+COMMAND("demo [<animation_mode=2>]")
 //=============================================================================
 {
     t_ilm_uint mode = (t_ilm_uint) input->getUint("animation_mode");
 //=============================================================================
 {
     t_ilm_uint mode = (t_ilm_uint) input->getUint("animation_mode");