Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

interpreter.cpp

00001 /*****************************************************************************
00002  * interpreter.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: interpreter.cpp 12281 2005-08-20 00:31:27Z dionoea $
00006  *
00007  * Authors: Cyril Deguet     <[email protected]>
00008  *          Olivier Teulière <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 #include "interpreter.hpp"
00026 #include "expr_evaluator.hpp"
00027 #include "../commands/cmd_muxer.hpp"
00028 #include "../commands/cmd_playlist.hpp"
00029 #include "../commands/cmd_playtree.hpp"
00030 #include "../commands/cmd_dialogs.hpp"
00031 #include "../commands/cmd_dummy.hpp"
00032 #include "../commands/cmd_layout.hpp"
00033 #include "../commands/cmd_quit.hpp"
00034 #include "../commands/cmd_minimize.hpp"
00035 #include "../commands/cmd_input.hpp"
00036 #include "../commands/cmd_fullscreen.hpp"
00037 #include "../commands/cmd_on_top.hpp"
00038 #include "../commands/cmd_show_window.hpp"
00039 #include "../src/theme.hpp"
00040 #include "../src/var_manager.hpp"
00041 #include "../src/vlcproc.hpp"
00042 
00043 
00044 Interpreter::Interpreter( intf_thread_t *pIntf ): SkinObject( pIntf )
00045 {
00047 #define REGISTER_CMD( name, cmd ) \
00048     m_commandMap[name] = CmdGenericPtr( new cmd( getIntf() ) );
00049 
00050     REGISTER_CMD( "none", CmdDummy )
00051     REGISTER_CMD( "dialogs.changeSkin()", CmdDlgChangeSkin )
00052     REGISTER_CMD( "dialogs.fileSimple()", CmdDlgFileSimple )
00053     REGISTER_CMD( "dialogs.file()", CmdDlgFile )
00054     REGISTER_CMD( "dialogs.directory()", CmdDlgDirectory )
00055     REGISTER_CMD( "dialogs.disc()", CmdDlgDisc )
00056     REGISTER_CMD( "dialogs.net()", CmdDlgNet )
00057     REGISTER_CMD( "dialogs.messages()", CmdDlgMessages )
00058     REGISTER_CMD( "dialogs.prefs()", CmdDlgPrefs )
00059     REGISTER_CMD( "dialogs.fileInfo()", CmdDlgFileInfo )
00060     REGISTER_CMD( "dialogs.streamingWizard()", CmdDlgStreamingWizard )
00061     REGISTER_CMD( "dialogs.popup()", CmdDlgShowPopupMenu )
00062     REGISTER_CMD( "playlist.load()", CmdDlgPlaylistLoad )
00063     REGISTER_CMD( "playlist.save()", CmdDlgPlaylistSave )
00064     REGISTER_CMD( "playlist.add()", CmdDlgAdd )
00065     VarList &rVar = VlcProc::instance( getIntf() )->getPlaylistVar();
00066     m_commandMap["playlist.del()"] =
00067         CmdGenericPtr( new CmdPlaylistDel( getIntf(), rVar ) );
00068     REGISTER_CMD( "playlist.next()", CmdPlaylistNext )
00069     REGISTER_CMD( "playlist.previous()", CmdPlaylistPrevious )
00070     REGISTER_CMD( "playlist.sort()", CmdPlaylistSort )
00071     m_commandMap["playlist.setRandom(true)"] =
00072         CmdGenericPtr( new CmdPlaylistRandom( getIntf(), true ) );
00073     m_commandMap["playlist.setRandom(false)"] =
00074         CmdGenericPtr( new CmdPlaylistRandom( getIntf(), false ) );
00075     m_commandMap["playlist.setLoop(true)"] =
00076         CmdGenericPtr( new CmdPlaylistLoop( getIntf(), true ) );
00077     m_commandMap["playlist.setLoop(false)"] =
00078         CmdGenericPtr( new CmdPlaylistLoop( getIntf(), false ) );
00079     m_commandMap["playlist.setRepeat(true)"] =
00080         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), true ) );
00081     m_commandMap["playlist.setRepeat(false)"] =
00082         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), false ) );
00083     REGISTER_CMD( "playtree.load()", CmdDlgPlaytreeLoad )
00084     REGISTER_CMD( "playtree.save()", CmdDlgPlaytreeSave )
00085     REGISTER_CMD( "playtree.add()", CmdDlgAdd )
00086     VarTree &rVarTree = VlcProc::instance( getIntf() )->getPlaytreeVar();
00087     m_commandMap["playtree.del()"] =
00088         CmdGenericPtr( new CmdPlaytreeDel( getIntf(), rVarTree ) );
00089     REGISTER_CMD( "playtree.next()", CmdPlaytreeNext )
00090     REGISTER_CMD( "playtree.previous()", CmdPlaytreePrevious )
00091     REGISTER_CMD( "playtree.sort()", CmdPlaytreeSort )
00092     m_commandMap["playtree.setRandom(true)"] =
00093         CmdGenericPtr( new CmdPlaytreeRandom( getIntf(), true ) );
00094     m_commandMap["playtree.setRandom(false)"] =
00095         CmdGenericPtr( new CmdPlaytreeRandom( getIntf(), false ) );
00096     m_commandMap["playtree.setLoop(true)"] =
00097         CmdGenericPtr( new CmdPlaytreeLoop( getIntf(), true ) );
00098     m_commandMap["playtree.setLoop(false)"] =
00099         CmdGenericPtr( new CmdPlaytreeLoop( getIntf(), false ) );
00100     m_commandMap["playtree.setRepeat(true)"] =
00101         CmdGenericPtr( new CmdPlaytreeRepeat( getIntf(), true ) );
00102     m_commandMap["playtree.setRepeat(false)"] =
00103         CmdGenericPtr( new CmdPlaytreeRepeat( getIntf(), false ) );
00104     REGISTER_CMD( "vlc.fullscreen()", CmdFullscreen )
00105     REGISTER_CMD( "vlc.play()", CmdPlay )
00106     REGISTER_CMD( "vlc.pause()", CmdPause )
00107     REGISTER_CMD( "vlc.stop()", CmdStop )
00108     REGISTER_CMD( "vlc.faster()", CmdFaster )
00109     REGISTER_CMD( "vlc.slower()", CmdSlower )
00110     REGISTER_CMD( "vlc.mute()", CmdMute )
00111     REGISTER_CMD( "vlc.volumeUp()", CmdVolumeUp )
00112     REGISTER_CMD( "vlc.volumeDown()", CmdVolumeDown )
00113     REGISTER_CMD( "vlc.minimize()", CmdMinimize )
00114     REGISTER_CMD( "vlc.onTop()", CmdOnTop )
00115     REGISTER_CMD( "vlc.quit()", CmdQuit )
00116 
00117     // Register the constant bool variables in the var manager
00118     VarManager *pVarManager = VarManager::instance( getIntf() );
00119     VarBool *pVarTrue = new VarBoolTrue( getIntf() );
00120     pVarManager->registerVar( VariablePtr( pVarTrue ), "true" );
00121     VarBool *pVarFalse = new VarBoolFalse( getIntf() );
00122     pVarManager->registerVar( VariablePtr( pVarFalse ), "false" );
00123 }
00124 
00125 
00126 Interpreter *Interpreter::instance( intf_thread_t *pIntf )
00127 {
00128     if( ! pIntf->p_sys->p_interpreter )
00129     {
00130         Interpreter *pInterpreter;
00131         pInterpreter = new Interpreter( pIntf );
00132         if( pInterpreter )
00133         {
00134             pIntf->p_sys->p_interpreter = pInterpreter;
00135         }
00136     }
00137     return pIntf->p_sys->p_interpreter;
00138 }
00139 
00140 
00141 void Interpreter::destroy( intf_thread_t *pIntf )
00142 {
00143     if( pIntf->p_sys->p_interpreter )
00144     {
00145         delete pIntf->p_sys->p_interpreter;
00146         pIntf->p_sys->p_interpreter = NULL;
00147     }
00148 }
00149 
00150 
00151 CmdGeneric *Interpreter::parseAction( const string &rAction, Theme *pTheme )
00152 {
00153     // Try to find the command in the global command map
00154     if( m_commandMap.find( rAction ) != m_commandMap.end() )
00155     {
00156         return m_commandMap[rAction].get();
00157     }
00158 
00159     CmdGeneric *pCommand = NULL;
00160 
00161     if( rAction.find( ";" ) != string::npos )
00162     {
00163         // Several actions are defined...
00164         list<CmdGeneric *> actionList;
00165         string rightPart = rAction;
00166         string::size_type pos = rightPart.find( ";" );
00167         while( pos != string::npos )
00168         {
00169             string leftPart = rightPart.substr( 0, rightPart.find( ";" ) );
00170             // Remove any whitespace at the end of the left part, and parse it
00171             leftPart =
00172                 leftPart.substr( 0, leftPart.find_last_not_of( " \t" ) + 1 );
00173             actionList.push_back( parseAction( leftPart, pTheme ) );
00174             // Now remove any whitespace at the beginning of the right part,
00175             // and go on checking for further actions in it...
00176             rightPart = rightPart.substr( pos, rightPart.size() );
00177             rightPart =
00178                 rightPart.substr( rightPart.find_first_not_of( " \t;" ),
00179                                   rightPart.size() );
00180             pos = rightPart.find( ";" );
00181         }
00182         actionList.push_back( parseAction( rightPart, pTheme ) );
00183 
00184         // The list is filled, we remove NULL pointers from it, just in case...
00185         actionList.remove( NULL );
00186 
00187         pCommand = new CmdMuxer( getIntf(), actionList );
00188     }
00189     else if( rAction.find( ".setLayout(" ) != string::npos )
00190     {
00191         int leftPos = rAction.find( ".setLayout(" );
00192         string windowId = rAction.substr( 0, leftPos );
00193         // 11 is the size of ".setLayout("
00194         int rightPos = rAction.find( ")", windowId.size() + 11 );
00195         string layoutId = rAction.substr( windowId.size() + 11,
00196                                           rightPos - (windowId.size() + 11) );
00197         pCommand = new CmdLayout( getIntf(), windowId, layoutId );
00198     }
00199     else if( rAction.find( ".show()" ) != string::npos )
00200     {
00201         int leftPos = rAction.find( ".show()" );
00202         string windowId = rAction.substr( 0, leftPos );
00203         TopWindow *pWin = pTheme->getWindowById( windowId );
00204         if( pWin )
00205         {
00206             pCommand = new CmdShowWindow( getIntf(), pTheme->getWindowManager(),
00207                                           *pWin );
00208         }
00209         else
00210         {
00211             msg_Err( getIntf(), "Unknown window (%s)", windowId.c_str() );
00212         }
00213     }
00214     else if( rAction.find( ".hide()" ) != string::npos )
00215     {
00216         int leftPos = rAction.find( ".hide()" );
00217         string windowId = rAction.substr( 0, leftPos );
00218         TopWindow *pWin = pTheme->getWindowById( windowId );
00219         if( pWin )
00220         {
00221             pCommand = new CmdHideWindow( getIntf(), pTheme->getWindowManager(),
00222                                           *pWin );
00223         }
00224         else
00225         {
00226             msg_Err( getIntf(), "Unknown window (%s)", windowId.c_str() );
00227         }
00228     }
00229 
00230     if( pCommand )
00231     {
00232         // Add the command in the pool
00233         pTheme->m_commands.push_back( CmdGenericPtr( pCommand ) );
00234     }
00235     else
00236     {
00237         msg_Warn( getIntf(), "Unknown action: %s", rAction.c_str() );
00238     }
00239 
00240     return pCommand;
00241 }
00242 
00243 
00244 VarBool *Interpreter::getVarBool( const string &rName, Theme *pTheme )
00245 {
00246     VarManager *pVarManager = VarManager::instance( getIntf() );
00247 
00248     // Convert the expression into Reverse Polish Notation
00249     ExprEvaluator evaluator( getIntf() );
00250     evaluator.parse( rName );
00251 
00252     list<VarBool*> varStack;
00253 
00254     // Get the first token from the RPN stack
00255     string token = evaluator.getToken();
00256     while( !token.empty() )
00257     {
00258         if( token == "and" )
00259         {
00260             // Get the 2 last variables on the stack
00261             if( varStack.empty() )
00262             {
00263                 msg_Err( getIntf(), "Invalid boolean expression: %s",
00264                          rName.c_str());
00265                 return NULL;
00266             }
00267             VarBool *pVar1 = varStack.back();
00268             varStack.pop_back();
00269             if( varStack.empty() )
00270             {
00271                 msg_Err( getIntf(), "Invalid boolean expression: %s",
00272                          rName.c_str());
00273                 return NULL;
00274             }
00275             VarBool *pVar2 = varStack.back();
00276             varStack.pop_back();
00277 
00278             // Create a composite boolean variable
00279             VarBool *pNewVar = new VarBoolAndBool( getIntf(), *pVar1, *pVar2 );
00280             varStack.push_back( pNewVar );
00281             // Register this variable in the manager
00282             pVarManager->registerVar( VariablePtr( pNewVar ) );
00283         }
00284         else if( token == "or" )
00285         {
00286             // Get the 2 last variables on the stack
00287             if( varStack.empty() )
00288             {
00289                 msg_Err( getIntf(), "Invalid boolean expression: %s",
00290                          rName.c_str());
00291                 return NULL;
00292             }
00293             VarBool *pVar1 = varStack.back();
00294             varStack.pop_back();
00295             if( varStack.empty() )
00296             {
00297                 msg_Err( getIntf(), "Invalid boolean expression: %s",
00298                          rName.c_str());
00299                 return NULL;
00300             }
00301             VarBool *pVar2 = varStack.back();
00302             varStack.pop_back();
00303 
00304             // Create a composite boolean variable
00305             VarBool *pNewVar = new VarBoolOrBool( getIntf(), *pVar1, *pVar2 );
00306             varStack.push_back( pNewVar );
00307             // Register this variable in the manager
00308             pVarManager->registerVar( VariablePtr( pNewVar ) );
00309         }
00310         else if( token == "not" )
00311         {
00312             // Get the last variable on the stack
00313             if( varStack.empty() )
00314             {
00315                 msg_Err( getIntf(), "Invalid boolean expression: %s",
00316                          rName.c_str());
00317                 return NULL;
00318             }
00319             VarBool *pVar = varStack.back();
00320             varStack.pop_back();
00321 
00322             // Create a composite boolean variable
00323             VarBool *pNewVar = new VarNotBool( getIntf(), *pVar );
00324             varStack.push_back( pNewVar );
00325             // Register this variable in the manager
00326             pVarManager->registerVar( VariablePtr( pNewVar ) );
00327         }
00328         else if( token.find( ".isVisible" ) != string::npos )
00329         {
00330             int leftPos = token.find( ".isVisible" );
00331             string windowId = token.substr( 0, leftPos );
00332             TopWindow *pWin = pTheme->getWindowById( windowId );
00333             if( pWin )
00334             {
00335                 // Push the visibility variable on the stack
00336                 varStack.push_back( &pWin->getVisibleVar() );
00337             }
00338             else
00339             {
00340                 msg_Err( getIntf(), "Unknown window (%s)", windowId.c_str() );
00341                 return NULL;
00342             }
00343         }
00344         else
00345         {
00346             // Try to get the variable from the variable manager
00347             VarBool *pVar = (VarBool*)pVarManager->getVar( token, "bool" );
00348             if( !pVar )
00349             {
00350                 msg_Err( getIntf(), "Cannot resolve boolean variable: %s",
00351                          token.c_str());
00352                 return NULL;
00353             }
00354             varStack.push_back( pVar );
00355         }
00356         // Get the first token from the RPN stack
00357         token = evaluator.getToken();
00358     }
00359 
00360     // The stack should contain a single variable
00361     if( varStack.size() != 1 )
00362     {
00363         msg_Err( getIntf(), "Invalid boolean expression: %s", rName.c_str() );
00364         return NULL;
00365     }
00366     return varStack.back();
00367 }
00368 
00369 
00370 VarPercent *Interpreter::getVarPercent( const string &rName, Theme *pTheme )
00371 {
00372     // Try to get the variable from the variable manager
00373     VarManager *pVarManager = VarManager::instance( getIntf() );
00374     VarPercent *pVar = (VarPercent*)pVarManager->getVar( rName, "percent" );
00375     return pVar;
00376 }
00377 
00378 
00379 VarList *Interpreter::getVarList( const string &rName, Theme *pTheme )
00380 {
00381     // Try to get the variable from the variable manager
00382     VarManager *pVarManager = VarManager::instance( getIntf() );
00383     VarList *pVar = (VarList*)pVarManager->getVar( rName, "list" );
00384     return pVar;
00385 }
00386 
00387 VarTree *Interpreter::getVarTree( const string &rName, Theme *pTheme )
00388 {
00389     // Try to get the variable from the variable manager
00390     VarManager *pVarManager = VarManager::instance( getIntf() );
00391     VarTree *pVar = (VarTree*)pVarManager->getVar( rName, "tree" );
00392     return pVar;
00393 }

Generated on Tue Dec 20 10:14:42 2005 for vlc-0.8.4a by  doxygen 1.4.2