mirror of
https://github.com/mickelson/attract.git
synced 2026-10-12 02:18:55 +00:00
Issue #121 - Added fe.nv table to squirrel, for persistent storage
Layouts and plugins can use the fe.nv table to store values which will be available the next time the layout or plugin is loaded. This table is shared between all layouts and plugins.
This commit is contained in:
@@ -45,6 +45,7 @@ Contents
|
||||
* [`fe.monitors`](#monitors)
|
||||
* [`fe.script_dir`](#script_dir)
|
||||
* [`fe.script_file`](#script_file)
|
||||
* [`fe.nv`](#nv)
|
||||
* [Classes](#classes)
|
||||
* [`fe.LayoutGlobals`](#LayoutGlobals)
|
||||
* [`fe.CurrentList`](#CurrentList)
|
||||
@@ -1049,6 +1050,14 @@ the layout or plug-in's directory.
|
||||
When Attract-Mode runs a layout or plug-in script, `fe.script_file` is set to
|
||||
the name of the layout or plug-in script file.
|
||||
|
||||
<a name="nv" />
|
||||
#### `fe.nv` ####
|
||||
|
||||
The fe.nv table can be used by layouts and plugins to store persistent values.
|
||||
The values in this table get saved by Attract-Mode whenever the layout changes
|
||||
and are saved to disk when Attract-Mode is shut down. Boolean, integer, float,
|
||||
string, array and table values can be stored in this table.
|
||||
|
||||
|
||||
<a name="classes" />
|
||||
Classes
|
||||
|
||||
@@ -63,7 +63,10 @@ class KonamiCode
|
||||
}
|
||||
|
||||
if ( m_commands.len() > 0 )
|
||||
{
|
||||
fe.add_ticks_callback( this, "on_tick" );
|
||||
fe.add_transition_callback( this, "on_transition" );
|
||||
}
|
||||
}
|
||||
|
||||
function on_tick( ttime )
|
||||
@@ -113,6 +116,24 @@ class KonamiCode
|
||||
fe.signal( m_config[ "action" ] );
|
||||
}
|
||||
}
|
||||
|
||||
function on_transition( ttype, var, ttime )
|
||||
{
|
||||
if ( ttype == Transition.StartLayout )
|
||||
{
|
||||
if ( fe.nv.rawin( "KonamiCode" ) )
|
||||
{
|
||||
m_current = fe.nv[ "KonamiCode" ];
|
||||
m_last_time = RESET_TIME / 2;
|
||||
delete fe.nv[ "KonamiCode" ];
|
||||
}
|
||||
}
|
||||
else if (( ttype == Transition.EndLayout )
|
||||
&& ( m_current > 0 ))
|
||||
{
|
||||
fe.nv[ "KonamiCode" ] <- m_current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an entry in the fe.plugin table in case anyone else wants to
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "fe_util_sq.hpp"
|
||||
#include "fe_util.hpp" // perform_substitution
|
||||
#include <sqrat.h>
|
||||
|
||||
bool fe_get_object_string(
|
||||
@@ -117,3 +118,122 @@ void fe_register_global_func(
|
||||
sq_newslot( vm, -3, SQFalse );
|
||||
sq_pop( vm, 1 ); // pops the root table
|
||||
}
|
||||
|
||||
std::string fe_to_json_string( HSQOBJECT obj, int indent )
|
||||
{
|
||||
std::string retval;
|
||||
Sqrat::Object sobj( obj );
|
||||
|
||||
switch ( sobj.GetType() )
|
||||
{
|
||||
case OT_NULL:
|
||||
retval = "null";
|
||||
break;
|
||||
|
||||
case OT_BOOL:
|
||||
case OT_INTEGER:
|
||||
case OT_FLOAT:
|
||||
fe_get_object_string( Sqrat::DefaultVM::Get(),
|
||||
obj, retval );
|
||||
break;
|
||||
|
||||
case OT_STRING:
|
||||
retval = "\"";
|
||||
{
|
||||
std::string obj_string;
|
||||
fe_get_object_string( Sqrat::DefaultVM::Get(),
|
||||
obj, obj_string );
|
||||
|
||||
perform_substitution( obj_string, "\"", "\\\"" );
|
||||
retval += obj_string;
|
||||
}
|
||||
retval += "\"";
|
||||
break;
|
||||
|
||||
case OT_TABLE:
|
||||
retval += "{\n";
|
||||
{
|
||||
for ( int i=0; i<indent; i++ )
|
||||
retval += "\t";
|
||||
|
||||
Sqrat::Object::iterator it;
|
||||
|
||||
bool first=true;
|
||||
bool got_obj = sobj.Next( it );
|
||||
while ( got_obj )
|
||||
{
|
||||
std::string val = fe_to_json_string( it.getValue(),
|
||||
indent+1 );
|
||||
|
||||
//
|
||||
// Ignore completely if val comes back empty
|
||||
//
|
||||
if ( val.empty() )
|
||||
{
|
||||
got_obj = sobj.Next( it );
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string key;
|
||||
fe_get_object_string( Sqrat::DefaultVM::Get(),
|
||||
it.getKey(), key );
|
||||
|
||||
perform_substitution( key, "\"", "\\\"" );
|
||||
|
||||
retval += "\t\"";
|
||||
retval += key;
|
||||
retval += "\": ";
|
||||
retval += val;
|
||||
|
||||
got_obj = sobj.Next( it );
|
||||
if ( got_obj )
|
||||
retval += ",";
|
||||
|
||||
retval += "\n";
|
||||
for ( int i=0; i<indent; i++ )
|
||||
retval += "\t";
|
||||
}
|
||||
}
|
||||
retval += "}";
|
||||
break;
|
||||
|
||||
case OT_ARRAY:
|
||||
retval += "[";
|
||||
{
|
||||
Sqrat::Object::iterator it;
|
||||
bool first=true;
|
||||
while ( sobj.Next( it ) )
|
||||
{
|
||||
std::string val = fe_to_json_string( it.getValue(),
|
||||
indent );
|
||||
|
||||
if ( !val.empty() )
|
||||
{
|
||||
if ( first )
|
||||
first=false;
|
||||
else
|
||||
retval += ",";
|
||||
|
||||
retval += val;
|
||||
}
|
||||
}
|
||||
}
|
||||
retval += "]";
|
||||
break;
|
||||
|
||||
case OT_USERDATA:
|
||||
case OT_CLOSURE:
|
||||
case OT_NATIVECLOSURE:
|
||||
case OT_GENERATOR:
|
||||
case OT_USERPOINTER:
|
||||
case OT_CLASS:
|
||||
case OT_INSTANCE:
|
||||
case OT_WEAKREF:
|
||||
default:
|
||||
// We return empty for these on purpose
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,4 +56,6 @@ void fe_register_global_func(
|
||||
SQFUNCTION f,
|
||||
const char *name );
|
||||
|
||||
std::string fe_to_json_string( HSQOBJECT obj, int indent=0 );
|
||||
|
||||
#endif
|
||||
|
||||
+84
-2
@@ -43,11 +43,14 @@
|
||||
#include <sqstdstring.h>
|
||||
#include <sqstdsystem.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <ctime>
|
||||
#include <stdarg.h>
|
||||
|
||||
const char *FE_SCRIPT_NV_FILE = "script.nv";
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
@@ -201,6 +204,34 @@ namespace
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string read_non_volatile_to_string( const SQChar *name )
|
||||
{
|
||||
Sqrat::Table fe( Sqrat::RootTable().GetSlot( _SC("fe") ) );
|
||||
Sqrat::Table snv( fe.GetSlot( name ) );
|
||||
|
||||
if ( snv.IsNull() )
|
||||
return "";
|
||||
|
||||
return fe_to_json_string( snv );
|
||||
}
|
||||
|
||||
void write_non_volatile_from_string( const char *name,
|
||||
std::string &nv )
|
||||
{
|
||||
if ( !nv.empty() )
|
||||
{
|
||||
std::string temp = "fe.";
|
||||
temp += name;
|
||||
temp += " <- ";
|
||||
temp += nv;
|
||||
temp += ";";
|
||||
|
||||
Sqrat::Script sc;
|
||||
sc.CompileString( temp );
|
||||
sc.Run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FeCallback::FeCallback( int pid,
|
||||
@@ -244,11 +275,47 @@ FeVM::FeVM( FeSettings &fes, FeFontContainer &defaultfont, FeWindow &wnd, FeSoun
|
||||
{
|
||||
srand( time( NULL ) );
|
||||
vm_init();
|
||||
|
||||
//
|
||||
// Read the "non-volatile" table (fe.nv) from the filesystem now
|
||||
//
|
||||
std::string filename = m_feSettings->get_config_dir();
|
||||
filename += FE_SCRIPT_NV_FILE;
|
||||
|
||||
std::ifstream infile( filename.c_str() );
|
||||
if ( !infile.is_open() )
|
||||
return;
|
||||
|
||||
std::string nv;
|
||||
while ( infile.good() )
|
||||
{
|
||||
std::string line;
|
||||
getline( infile, line );
|
||||
nv += line;
|
||||
}
|
||||
|
||||
Sqrat::Table fe;
|
||||
Sqrat::RootTable().Bind( _SC("fe"), fe );
|
||||
write_non_volatile_from_string( "nv", nv );
|
||||
}
|
||||
|
||||
FeVM::~FeVM()
|
||||
{
|
||||
clear();
|
||||
|
||||
//
|
||||
// Save the "non-volatile" squirrel table (fe.nv) to a file now
|
||||
//
|
||||
std::string filename = m_feSettings->get_config_dir();
|
||||
filename += FE_SCRIPT_NV_FILE;
|
||||
|
||||
std::ofstream outfile( filename.c_str() );
|
||||
if ( outfile.is_open() )
|
||||
{
|
||||
outfile << read_non_volatile_to_string( _SC( "nv" ) ) << std::endl;
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
vm_close();
|
||||
}
|
||||
|
||||
@@ -351,6 +418,7 @@ void FeVM::vm_init()
|
||||
Sqrat::DefaultVM::Set( vm );
|
||||
}
|
||||
|
||||
|
||||
bool FeVM::on_new_layout()
|
||||
{
|
||||
using namespace Sqrat;
|
||||
@@ -358,7 +426,11 @@ bool FeVM::on_new_layout()
|
||||
const FeLayoutInfo &layout_params
|
||||
= m_feSettings->get_current_config( FeSettings::Current );
|
||||
|
||||
vm_close();
|
||||
|
||||
// Grab the contents of the existing "non-volatile" squirrel table
|
||||
// before reinitializing
|
||||
//
|
||||
std::string nv = read_non_volatile_to_string( _SC( "nv" ) );
|
||||
|
||||
// Squirrel VM gets reinitialized on each layout
|
||||
//
|
||||
@@ -724,6 +796,11 @@ bool FeVM::on_new_layout()
|
||||
fe.SetInstance( _SC("ambient_sound"), &m_ambient_sound );
|
||||
fe.SetValue( _SC("plugin"), Table() ); // an empty table for plugins to use/abuse
|
||||
|
||||
// We keep a "non-volatile" table for use by layouts/plugins, the
|
||||
// string content of which gets copied over from layout to layout
|
||||
//
|
||||
fe.SetValue( _SC("nv"), Table() );
|
||||
|
||||
// Each presentation object gets an instance in the
|
||||
// "obj" array available in Squirrel
|
||||
//
|
||||
@@ -731,6 +808,8 @@ bool FeVM::on_new_layout()
|
||||
fe.Bind( _SC("obj"), obj );
|
||||
RootTable().Bind( _SC("fe"), fe );
|
||||
|
||||
write_non_volatile_from_string( "nv", nv );
|
||||
|
||||
//
|
||||
// Run the layout script
|
||||
//
|
||||
@@ -1172,6 +1251,9 @@ public:
|
||||
sqstd_register_systemlib( m_vm );
|
||||
// sqstd_seterrorhandlers( m_vm ); // don't set this on purpose
|
||||
|
||||
fe_register_global_func( m_vm, zip_extract_file, "zip_extract_file" );
|
||||
fe_register_global_func( m_vm, zip_get_dir, "zip_get_dir" );
|
||||
|
||||
Sqrat::DefaultVM::Set( m_vm );
|
||||
|
||||
Sqrat::ConstTable()
|
||||
@@ -1232,7 +1314,7 @@ public:
|
||||
|
||||
fe.SetValue( _SC("loader_dir"), path );
|
||||
}
|
||||
run_script( path, file, true );
|
||||
run_script( path, file, false );
|
||||
};
|
||||
|
||||
~FeConfigVM()
|
||||
|
||||
Reference in New Issue
Block a user