00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
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
00171 leftPart =
00172 leftPart.substr( 0, leftPart.find_last_not_of( " \t" ) + 1 );
00173 actionList.push_back( parseAction( leftPart, pTheme ) );
00174
00175
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
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
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
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
00249 ExprEvaluator evaluator( getIntf() );
00250 evaluator.parse( rName );
00251
00252 list<VarBool*> varStack;
00253
00254
00255 string token = evaluator.getToken();
00256 while( !token.empty() )
00257 {
00258 if( token == "and" )
00259 {
00260
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
00279 VarBool *pNewVar = new VarBoolAndBool( getIntf(), *pVar1, *pVar2 );
00280 varStack.push_back( pNewVar );
00281
00282 pVarManager->registerVar( VariablePtr( pNewVar ) );
00283 }
00284 else if( token == "or" )
00285 {
00286
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
00305 VarBool *pNewVar = new VarBoolOrBool( getIntf(), *pVar1, *pVar2 );
00306 varStack.push_back( pNewVar );
00307
00308 pVarManager->registerVar( VariablePtr( pNewVar ) );
00309 }
00310 else if( token == "not" )
00311 {
00312
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
00323 VarBool *pNewVar = new VarNotBool( getIntf(), *pVar );
00324 varStack.push_back( pNewVar );
00325
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
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
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
00357 token = evaluator.getToken();
00358 }
00359
00360
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
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
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
00390 VarManager *pVarManager = VarManager::instance( getIntf() );
00391 VarTree *pVar = (VarTree*)pVarManager->getVar( rName, "tree" );
00392 return pVar;
00393 }