interpreter.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:20k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * interpreter.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 the VideoLAN team
  5.  * $Id: 5f3ae2223c8a052468184be2a5b2a829ebc1858a $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teulière <ipkiss@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #include "interpreter.hpp"
  25. #include "expr_evaluator.hpp"
  26. #include "../commands/cmd_audio.hpp"
  27. #include "../commands/cmd_muxer.hpp"
  28. #include "../commands/cmd_playlist.hpp"
  29. #include "../commands/cmd_playtree.hpp"
  30. #include "../commands/cmd_dialogs.hpp"
  31. #include "../commands/cmd_dummy.hpp"
  32. #include "../commands/cmd_dvd.hpp"
  33. #include "../commands/cmd_layout.hpp"
  34. #include "../commands/cmd_quit.hpp"
  35. #include "../commands/cmd_minimize.hpp"
  36. #include "../commands/cmd_input.hpp"
  37. #include "../commands/cmd_fullscreen.hpp"
  38. #include "../commands/cmd_on_top.hpp"
  39. #include "../commands/cmd_show_window.hpp"
  40. #include "../commands/cmd_snapshot.hpp"
  41. #include "../src/theme.hpp"
  42. #include "../src/var_manager.hpp"
  43. #include "../src/vlcproc.hpp"
  44. Interpreter::Interpreter( intf_thread_t *pIntf ): SkinObject( pIntf )
  45. {
  46.     /// Create the generic commands
  47. #define REGISTER_CMD( name, cmd ) 
  48.     m_commandMap[name] = CmdGenericPtr( new cmd( getIntf() ) );
  49.     REGISTER_CMD( "none", CmdDummy )
  50.     REGISTER_CMD( "dialogs.changeSkin()", CmdDlgChangeSkin )
  51.     REGISTER_CMD( "dialogs.fileSimple()", CmdDlgFileSimple )
  52.     REGISTER_CMD( "dialogs.file()", CmdDlgFile )
  53.     REGISTER_CMD( "dialogs.directory()", CmdDlgDirectory )
  54.     REGISTER_CMD( "dialogs.disc()", CmdDlgDisc )
  55.     REGISTER_CMD( "dialogs.net()", CmdDlgNet )
  56.     REGISTER_CMD( "dialogs.playlist()", CmdDlgPlaylist )
  57.     REGISTER_CMD( "dialogs.messages()", CmdDlgMessages )
  58.     REGISTER_CMD( "dialogs.prefs()", CmdDlgPrefs )
  59.     REGISTER_CMD( "dialogs.fileInfo()", CmdDlgFileInfo )
  60.     REGISTER_CMD( "dialogs.streamingWizard()", CmdDlgStreamingWizard )
  61.     REGISTER_CMD( "dialogs.popup()", CmdDlgShowPopupMenu )
  62.     REGISTER_CMD( "dialogs.audioPopup()", CmdDlgShowAudioPopupMenu )
  63.     REGISTER_CMD( "dialogs.videoPopup()", CmdDlgShowVideoPopupMenu )
  64.     REGISTER_CMD( "dialogs.miscPopup()", CmdDlgShowMiscPopupMenu )
  65.     REGISTER_CMD( "dvd.nextTitle()", CmdDvdNextTitle )
  66.     REGISTER_CMD( "dvd.previousTitle()", CmdDvdPreviousTitle )
  67.     REGISTER_CMD( "dvd.nextChapter()", CmdDvdNextChapter )
  68.     REGISTER_CMD( "dvd.previousChapter()", CmdDvdPreviousChapter )
  69.     REGISTER_CMD( "dvd.rootMenu()", CmdDvdRootMenu )
  70.     REGISTER_CMD( "playlist.load()", CmdDlgPlaylistLoad )
  71.     REGISTER_CMD( "playlist.save()", CmdDlgPlaylistSave )
  72.     REGISTER_CMD( "playlist.add()", CmdDlgAdd )
  73.     REGISTER_CMD( "playlist.next()", CmdPlaylistNext )
  74.     REGISTER_CMD( "playlist.previous()", CmdPlaylistPrevious )
  75.     m_commandMap["playlist.setRandom(true)"] =
  76.         CmdGenericPtr( new CmdPlaylistRandom( getIntf(), true ) );
  77.     m_commandMap["playlist.setRandom(false)"] =
  78.         CmdGenericPtr( new CmdPlaylistRandom( getIntf(), false ) );
  79.     m_commandMap["playlist.setLoop(true)"] =
  80.         CmdGenericPtr( new CmdPlaylistLoop( getIntf(), true ) );
  81.     m_commandMap["playlist.setLoop(false)"] =
  82.         CmdGenericPtr( new CmdPlaylistLoop( getIntf(), false ) );
  83.     m_commandMap["playlist.setRepeat(true)"] =
  84.         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), true ) );
  85.     m_commandMap["playlist.setRepeat(false)"] =
  86.         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), false ) );
  87.     VarTree &rVarTree = VlcProc::instance( getIntf() )->getPlaytreeVar();
  88.     m_commandMap["playlist.del()"] =
  89.         CmdGenericPtr( new CmdPlaytreeDel( getIntf(), rVarTree ) );
  90.     m_commandMap["playtree.del()"] =
  91.         CmdGenericPtr( new CmdPlaytreeDel( getIntf(), rVarTree ) );
  92.     REGISTER_CMD( "playlist.sort()", CmdPlaytreeSort )
  93.     REGISTER_CMD( "playtree.sort()", CmdPlaytreeSort )
  94.     REGISTER_CMD( "vlc.fullscreen()", CmdFullscreen )
  95.     REGISTER_CMD( "vlc.play()", CmdPlay )
  96.     REGISTER_CMD( "vlc.pause()", CmdPause )
  97.     REGISTER_CMD( "vlc.stop()", CmdStop )
  98.     REGISTER_CMD( "vlc.faster()", CmdFaster )
  99.     REGISTER_CMD( "vlc.slower()", CmdSlower )
  100.     REGISTER_CMD( "vlc.mute()", CmdMute )
  101.     REGISTER_CMD( "vlc.volumeUp()", CmdVolumeUp )
  102.     REGISTER_CMD( "vlc.volumeDown()", CmdVolumeDown )
  103.     REGISTER_CMD( "vlc.minimize()", CmdMinimize )
  104.     REGISTER_CMD( "vlc.onTop()", CmdOnTop )
  105.     REGISTER_CMD( "vlc.snapshot()", CmdSnapshot )
  106.     REGISTER_CMD( "vlc.quit()", CmdQuit )
  107.     m_commandMap["equalizer.enable()"] =
  108.         CmdGenericPtr( new CmdSetEqualizer( getIntf(), true ) );
  109.     m_commandMap["equalizer.disable()"] =
  110.         CmdGenericPtr( new CmdSetEqualizer( getIntf(), false ) );
  111.     // Register the constant bool variables in the var manager
  112.     VarManager *pVarManager = VarManager::instance( getIntf() );
  113.     VarBool *pVarTrue = new VarBoolTrue( getIntf() );
  114.     pVarManager->registerVar( VariablePtr( pVarTrue ), "true" );
  115.     VarBool *pVarFalse = new VarBoolFalse( getIntf() );
  116.     pVarManager->registerVar( VariablePtr( pVarFalse ), "false" );
  117. }
  118. Interpreter *Interpreter::instance( intf_thread_t *pIntf )
  119. {
  120.     if( ! pIntf->p_sys->p_interpreter )
  121.     {
  122.         Interpreter *pInterpreter;
  123.         pInterpreter = new Interpreter( pIntf );
  124.         if( pInterpreter )
  125.         {
  126.             pIntf->p_sys->p_interpreter = pInterpreter;
  127.         }
  128.     }
  129.     return pIntf->p_sys->p_interpreter;
  130. }
  131. void Interpreter::destroy( intf_thread_t *pIntf )
  132. {
  133.     if( pIntf->p_sys->p_interpreter )
  134.     {
  135.         delete pIntf->p_sys->p_interpreter;
  136.         pIntf->p_sys->p_interpreter = NULL;
  137.     }
  138. }
  139. CmdGeneric *Interpreter::parseAction( const string &rAction, Theme *pTheme )
  140. {
  141.     // Try to find the command in the global command map
  142.     if( m_commandMap.find( rAction ) != m_commandMap.end() )
  143.     {
  144.         return m_commandMap[rAction].get();
  145.     }
  146.     CmdGeneric *pCommand = NULL;
  147.     if( rAction.find( ";" ) != string::npos )
  148.     {
  149.         // Several actions are defined...
  150.         list<CmdGeneric *> actionList;
  151.         string rightPart = rAction;
  152.         string::size_type pos = rightPart.find( ";" );
  153.         while( pos != string::npos )
  154.         {
  155.             string leftPart = rightPart.substr( 0, pos );
  156.             // Remove any whitespace at the end of the left part, and parse it
  157.             leftPart =
  158.                 leftPart.substr( 0, leftPart.find_last_not_of( " t" ) + 1 );
  159.             actionList.push_back( parseAction( leftPart, pTheme ) );
  160.             // Now remove any whitespace at the beginning of the right part,
  161.             // and go on checking for further actions in it...
  162.             rightPart = rightPart.substr( pos, rightPart.size() );
  163.             if ( rightPart.find_first_not_of( " t;" ) == string::npos )
  164.             {
  165.                 // The right part is completely buggy, it's time to leave the
  166.                 // loop...
  167.                 rightPart = "";
  168.                 break;
  169.             }
  170.             rightPart =
  171.                 rightPart.substr( rightPart.find_first_not_of( " t;" ),
  172.                                   rightPart.size() );
  173.             pos = rightPart.find( ";" );
  174.         }
  175.         actionList.push_back( parseAction( rightPart, pTheme ) );
  176.         // The list is filled, we remove NULL pointers from it, just in case...
  177.         actionList.remove( NULL );
  178.         pCommand = new CmdMuxer( getIntf(), actionList );
  179.     }
  180.     else if( rAction.find( ".setLayout(" ) != string::npos )
  181.     {
  182.         int leftPos = rAction.find( ".setLayout(" );
  183.         string windowId = rAction.substr( 0, leftPos );
  184.         // 11 is the size of ".setLayout("
  185.         int rightPos = rAction.find( ")", windowId.size() + 11 );
  186.         string layoutId = rAction.substr( windowId.size() + 11,
  187.                                           rightPos - (windowId.size() + 11) );
  188.         TopWindow *pWin = pTheme->getWindowById( windowId );
  189.         GenericLayout *pLayout = pTheme->getLayoutById( layoutId );
  190.         if( !pWin )
  191.         {
  192.             msg_Err( getIntf(), "unknown window (%s)", windowId.c_str() );
  193.         }
  194.         else if( !pLayout )
  195.         {
  196.             msg_Err( getIntf(), "unknown layout (%s)", layoutId.c_str() );
  197.         }
  198.         // Check that the layout doesn't correspond to another window
  199.         else if( pWin != pLayout->getWindow() )
  200.         {
  201.             msg_Err( getIntf(), "layout %s is not associated to window %s",
  202.                      layoutId.c_str(), windowId.c_str() );
  203.         }
  204.         else
  205.         {
  206.             pCommand = new CmdLayout( getIntf(), *pWin, *pLayout );
  207.         }
  208.     }
  209.     else if( rAction.find( ".maximize()" ) != string::npos )
  210.     {
  211.         int leftPos = rAction.find( ".maximize()" );
  212.         string windowId = rAction.substr( 0, leftPos );
  213.         TopWindow *pWin = pTheme->getWindowById( windowId );
  214.         if( !pWin )
  215.         {
  216.             msg_Err( getIntf(), "unknown window (%s)", windowId.c_str() );
  217.         }
  218.         else
  219.         {
  220.             pCommand = new CmdMaximize( getIntf(),
  221.                                         pTheme->getWindowManager(),
  222.                                         *pWin );
  223.         }
  224.     }
  225.     else if( rAction.find( ".unmaximize()" ) != string::npos )
  226.     {
  227.         int leftPos = rAction.find( ".unmaximize()" );
  228.         string windowId = rAction.substr( 0, leftPos );
  229.         TopWindow *pWin = pTheme->getWindowById( windowId );
  230.         if( !pWin )
  231.         {
  232.             msg_Err( getIntf(), "unknown window (%s)", windowId.c_str() );
  233.         }
  234.         else
  235.         {
  236.             pCommand = new CmdUnmaximize( getIntf(),
  237.                                           pTheme->getWindowManager(),
  238.                                           *pWin );
  239.         }
  240.     }
  241.     else if( rAction.find( ".show()" ) != string::npos )
  242.     {
  243.         int leftPos = rAction.find( ".show()" );
  244.         string windowId = rAction.substr( 0, leftPos );
  245.         if( windowId == "playlist_window" &&
  246.             !config_GetInt( getIntf(), "skinned-playlist") )
  247.         {
  248.             list<CmdGeneric *> list;
  249.             list.push_back( new CmdDlgPlaylist( getIntf() ) );
  250.             TopWindow *pWin = pTheme->getWindowById( windowId );
  251.             if( pWin )
  252.                 list.push_back( new CmdHideWindow( getIntf(),
  253.                                                    pTheme->getWindowManager(),
  254.                                                    *pWin ) );
  255.             pCommand = new CmdMuxer( getIntf(), list );
  256.         }
  257.         else
  258.         {
  259.             TopWindow *pWin = pTheme->getWindowById( windowId );
  260.             if( pWin )
  261.             {
  262.                 pCommand = new CmdShowWindow( getIntf(),
  263.                                               pTheme->getWindowManager(),
  264.                                               *pWin );
  265.             }
  266.             else
  267.             {
  268.                 // It was maybe the id of a popup
  269.                 Popup *pPopup = pTheme->getPopupById( windowId );
  270.                 if( pPopup )
  271.                 {
  272.                     pCommand = new CmdShowPopup( getIntf(), *pPopup );
  273.                 }
  274.                 else
  275.                 {
  276.                     msg_Err( getIntf(), "unknown window or popup (%s)",
  277.                              windowId.c_str() );
  278.                 }
  279.             }
  280.         }
  281.     }
  282.     else if( rAction.find( ".hide()" ) != string::npos )
  283.     {
  284.         int leftPos = rAction.find( ".hide()" );
  285.         string windowId = rAction.substr( 0, leftPos );
  286.         if( windowId == "playlist_window" &&
  287.            ! config_GetInt( getIntf(), "skinned-playlist") )
  288.         {
  289.             list<CmdGeneric *> list;
  290.             list.push_back( new CmdDlgPlaylist( getIntf() ) );
  291.             TopWindow *pWin = pTheme->getWindowById( windowId );
  292.             if( pWin )
  293.                 list.push_back( new CmdHideWindow( getIntf(),
  294.                                                    pTheme->getWindowManager(),
  295.                                                    *pWin ) );
  296.             pCommand = new CmdMuxer( getIntf(), list );
  297.         }
  298.         else
  299.         {
  300.             TopWindow *pWin = pTheme->getWindowById( windowId );
  301.             if( pWin )
  302.             {
  303.                 pCommand = new CmdHideWindow( getIntf(),
  304.                                               pTheme->getWindowManager(),
  305.                                               *pWin );
  306.             }
  307.             else
  308.             {
  309.                 msg_Err( getIntf(), "unknown window (%s)", windowId.c_str() );
  310.             }
  311.         }
  312.     }
  313.     if( pCommand )
  314.     {
  315.         // Add the command in the pool
  316.         pTheme->m_commands.push_back( CmdGenericPtr( pCommand ) );
  317.     }
  318.     else
  319.     {
  320.         msg_Warn( getIntf(), "unknown action: %s", rAction.c_str() );
  321.     }
  322.     return pCommand;
  323. }
  324. VarBool *Interpreter::getVarBool( const string &rName, Theme *pTheme )
  325. {
  326.     VarManager *pVarManager = VarManager::instance( getIntf() );
  327.     // Convert the expression into Reverse Polish Notation
  328.     ExprEvaluator evaluator( getIntf() );
  329.     evaluator.parse( rName );
  330.     list<VarBool*> varStack;
  331.     // Get the first token from the RPN stack
  332.     string token = evaluator.getToken();
  333.     while( !token.empty() )
  334.     {
  335.         if( token == "and" )
  336.         {
  337.             // Get the 2 last variables on the stack
  338.             if( varStack.empty() )
  339.             {
  340.                 msg_Err( getIntf(), "invalid boolean expression: %s",
  341.                          rName.c_str());
  342.                 return NULL;
  343.             }
  344.             VarBool *pVar1 = varStack.back();
  345.             varStack.pop_back();
  346.             if( varStack.empty() )
  347.             {
  348.                 msg_Err( getIntf(), "invalid boolean expression: %s",
  349.                          rName.c_str());
  350.                 return NULL;
  351.             }
  352.             VarBool *pVar2 = varStack.back();
  353.             varStack.pop_back();
  354.             // Create a composite boolean variable
  355.             VarBool *pNewVar = new VarBoolAndBool( getIntf(), *pVar1, *pVar2 );
  356.             varStack.push_back( pNewVar );
  357.             // Register this variable in the manager
  358.             pVarManager->registerVar( VariablePtr( pNewVar ) );
  359.         }
  360.         else if( token == "or" )
  361.         {
  362.             // Get the 2 last variables on the stack
  363.             if( varStack.empty() )
  364.             {
  365.                 msg_Err( getIntf(), "invalid boolean expression: %s",
  366.                          rName.c_str());
  367.                 return NULL;
  368.             }
  369.             VarBool *pVar1 = varStack.back();
  370.             varStack.pop_back();
  371.             if( varStack.empty() )
  372.             {
  373.                 msg_Err( getIntf(), "invalid boolean expression: %s",
  374.                          rName.c_str());
  375.                 return NULL;
  376.             }
  377.             VarBool *pVar2 = varStack.back();
  378.             varStack.pop_back();
  379.             // Create a composite boolean variable
  380.             VarBool *pNewVar = new VarBoolOrBool( getIntf(), *pVar1, *pVar2 );
  381.             varStack.push_back( pNewVar );
  382.             // Register this variable in the manager
  383.             pVarManager->registerVar( VariablePtr( pNewVar ) );
  384.         }
  385.         else if( token == "not" )
  386.         {
  387.             // Get the last variable on the stack
  388.             if( varStack.empty() )
  389.             {
  390.                 msg_Err( getIntf(), "invalid boolean expression: %s",
  391.                          rName.c_str());
  392.                 return NULL;
  393.             }
  394.             VarBool *pVar = varStack.back();
  395.             varStack.pop_back();
  396.             // Create a composite boolean variable
  397.             VarBool *pNewVar = new VarNotBool( getIntf(), *pVar );
  398.             varStack.push_back( pNewVar );
  399.             // Register this variable in the manager
  400.             pVarManager->registerVar( VariablePtr( pNewVar ) );
  401.         }
  402.         else
  403.         {
  404.             // Try first to get the variable from the variable manager
  405.             // Indeed, if the skin designer is stupid enough to call a layout
  406.             // "dvd", we want "dvd.isActive" to resolve as the built-in action
  407.             // and not as the "layoutId.isActive" one.
  408.             VarBool *pVar = (VarBool*)pVarManager->getVar( token, "bool" );
  409.             if( pVar )
  410.             {
  411.                 varStack.push_back( pVar );
  412.             }
  413.             else if( token.find( ".isVisible" ) != string::npos )
  414.             {
  415.                 int leftPos = token.find( ".isVisible" );
  416.                 string windowId = token.substr( 0, leftPos );
  417.                 TopWindow *pWin = pTheme->getWindowById( windowId );
  418.                 if( pWin )
  419.                 {
  420.                     // Push the visibility variable onto the stack
  421.                     varStack.push_back( &pWin->getVisibleVar() );
  422.                 }
  423.                 else
  424.                 {
  425.                     msg_Err( getIntf(), "unknown window (%s)",
  426.                              windowId.c_str() );
  427.                     return NULL;
  428.                 }
  429.             }
  430.             else if( token.find( ".isMaximized" ) != string::npos )
  431.             {
  432.                 int leftPos = token.find( ".isMaximized" );
  433.                 string windowId = token.substr( 0, leftPos );
  434.                 TopWindow *pWin = pTheme->getWindowById( windowId );
  435.                 if( pWin )
  436.                 {
  437.                     // Push the "maximized" variable onto the stack
  438.                     varStack.push_back( &pWin->getMaximizedVar() );
  439.                 }
  440.                 else
  441.                 {
  442.                     msg_Err( getIntf(), "unknown window (%s)",
  443.                              windowId.c_str() );
  444.                     return NULL;
  445.                 }
  446.             }
  447.             else if( token.find( ".isActive" ) != string::npos )
  448.             {
  449.                 int leftPos = token.find( ".isActive" );
  450.                 string layoutId = token.substr( 0, leftPos );
  451.                 GenericLayout *pLayout = pTheme->getLayoutById( layoutId );
  452.                 if( pLayout )
  453.                 {
  454.                     // Push the isActive variable onto the stack
  455.                     varStack.push_back( &pLayout->getActiveVar() );
  456.                 }
  457.                 else
  458.                 {
  459.                     msg_Err( getIntf(), "unknown layout (%s)",
  460.                              layoutId.c_str() );
  461.                     return NULL;
  462.                 }
  463.             }
  464.             else
  465.             {
  466.                 msg_Err( getIntf(), "cannot resolve boolean variable: %s",
  467.                          token.c_str());
  468.                 return NULL;
  469.             }
  470.         }
  471.         // Get the first token from the RPN stack
  472.         token = evaluator.getToken();
  473.     }
  474.     // The stack should contain a single variable
  475.     if( varStack.size() != 1 )
  476.     {
  477.         msg_Err( getIntf(), "invalid boolean expression: %s", rName.c_str() );
  478.         return NULL;
  479.     }
  480.     return varStack.back();
  481. }
  482. VarPercent *Interpreter::getVarPercent( const string &rName, Theme *pTheme )
  483. {
  484.     // Try to get the variable from the variable manager
  485.     VarManager *pVarManager = VarManager::instance( getIntf() );
  486.     VarPercent *pVar = (VarPercent*)pVarManager->getVar( rName, "percent" );
  487.     return pVar;
  488. }
  489. VarList *Interpreter::getVarList( const string &rName, Theme *pTheme )
  490. {
  491.     // Try to get the variable from the variable manager
  492.     VarManager *pVarManager = VarManager::instance( getIntf() );
  493.     VarList *pVar = (VarList*)pVarManager->getVar( rName, "list" );
  494.     return pVar;
  495. }
  496. VarTree *Interpreter::getVarTree( const string &rName, Theme *pTheme )
  497. {
  498.     // Try to get the variable from the variable manager
  499.     VarManager *pVarManager = VarManager::instance( getIntf() );
  500.     VarTree *pVar = (VarTree*)pVarManager->getVar( rName, "tree" );
  501.     return pVar;
  502. }
  503. string Interpreter::getConstant( const string &rValue )
  504. {
  505.     // Check if the value is a registered constant
  506.     string val = VarManager::instance( getIntf() )->getConst( rValue );
  507.     if( val.empty() )
  508.     {
  509.         // if not, keep the value as is
  510.         val = rValue;
  511.     }
  512.     return val;
  513. }