From 08e5fbdcc2ecbf0258055e503779493dfeadff06 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 26 Jul 2012 20:44:33 -0700 Subject: [PATCH] add ability to open game in sqlite3 DB from an Android phone. It's read-only now: changes are not saved. But it works! --- xwords4/linux/Makefile | 2 +- xwords4/linux/cursesmain.c | 13 +++++++---- xwords4/linux/gtkmain.c | 5 +++- xwords4/linux/linuxmain.c | 48 +++++++++++++++++++++++++++++++++++++- xwords4/linux/linuxmain.h | 1 + xwords4/linux/main.h | 2 ++ 6 files changed, 64 insertions(+), 7 deletions(-) diff --git a/xwords4/linux/Makefile b/xwords4/linux/Makefile index 4e3ee8ffe..6b2da18f6 100644 --- a/xwords4/linux/Makefile +++ b/xwords4/linux/Makefile @@ -189,7 +189,7 @@ OBJ = \ $(PLATFORM)/linuxutl.o \ $(CURSES_OBJS) $(GTK_OBJS) $(MAIN_OBJS) -LIBS = -lm -luuid $(GPROFFLAG) +LIBS = -lm -luuid -lsqlite3 $(GPROFFLAG) # Turn this off for now. I apparently have a memory problem, but it # doesn't make the app unusable for testing while crash on boot does. # LIBS += -lmcheck diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index b9567fd7e..3e8ff9f3c 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -1770,18 +1770,22 @@ cursesmain( XP_Bool isServer, LaunchParams* params ) } else if ( !!params->nbs && !!params->fileName ) { do_nbs_then_close( &g_globals.cGlobals, &procs ); } else { - + XP_Bool opened = XP_FALSE; initCurses( &g_globals ); getmaxyx( g_globals.boardWin, height, width ); g_globals.draw = (struct CursesDrawCtx*) cursesDrawCtxtMake( g_globals.boardWin ); + XWStreamCtxt* stream = NULL; if ( !!params->fileName && file_exists( params->fileName ) ) { - XWStreamCtxt* stream; stream = streamFromFile( &g_globals.cGlobals, params->fileName, &g_globals ); + } else if ( !!params->dbFileName && file_exists( params->dbFileName ) ) { + stream = streamFromDB( &g_globals.cGlobals, &g_globals ); + } + if ( !!stream ) { (void)game_makeFromStream( MEMPOOL stream, &g_globals.cGlobals.game, ¶ms->gi, params->dict, ¶ms->dicts, params->util, @@ -1789,11 +1793,12 @@ cursesmain( XP_Bool isServer, LaunchParams* params ) &g_globals.cGlobals.cp, &procs ); stream_destroy( stream ); - if ( !isServer && params->gi.serverRole == SERVER_ISSERVER ) { isServer = XP_TRUE; } - } else { + opened = XP_TRUE; + } + if ( !opened ) { game_makeNewGame( MEMPOOL &g_globals.cGlobals.game, ¶ms->gi, params->util, (DrawCtx*)g_globals.draw, &g_globals.cGlobals.cp, &procs, params->gameSeed ); diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index d5ed18bb8..79326b23a 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -417,9 +417,12 @@ createOrLoadObjects( GtkAppGlobals* globals ) }; if ( !!params->fileName && file_exists( params->fileName ) ) { - stream = streamFromFile( &globals->cGlobals, params->fileName, globals ); + } else if ( !!params->dbFileName && file_exists( params->dbFileName ) ) { + stream = streamFromDB( &globals->cGlobals, globals ); + } + if ( !!stream ) { opened = game_makeFromStream( MEMPOOL stream, &globals->cGlobals.game, &globals->cGlobals.params->gi, params->dict, ¶ms->dicts, params->util, diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index 4d1f84ed9..78771b1a3 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef XWFEATURE_BLUETOOTH # include @@ -104,6 +105,42 @@ streamFromFile( CommonGlobals* cGlobals, char* name, void* closure ) return stream; } /* streamFromFile */ +XWStreamCtxt* +streamFromDB( CommonGlobals* cGlobals, void* closure ) +{ + XWStreamCtxt* stream = NULL; + const LaunchParams* params = cGlobals->params; + const char* name = params->dbFileName; + XP_U32 rowid = params->dbFileID; + sqlite3* ppDb; + int res = sqlite3_open( name, &ppDb ); + if ( SQLITE_OK == res ) { + sqlite3_blob* ppBlob; + res = sqlite3_blob_open( ppDb, "main", "summaries", "SNAPSHOT", rowid, + 0 /*flags*/, &ppBlob ); + if ( SQLITE_OK == res ) { + int size = sqlite3_blob_bytes( ppBlob ); + XP_U8 buf[size]; + res = sqlite3_blob_read( ppBlob, buf, size, 0 ); + if ( SQLITE_OK == res ) { + stream = mem_stream_make( MPPARM(params->util->mpool) params->vtMgr, + closure, CHANNEL_NONE, NULL ); + stream_putBytes( stream, buf, size ); + } + } + sqlite3_blob_close( ppBlob ); + } + + if ( SQLITE_OK != res ) { + XP_LOGF( "%s: error from sqlite: %s", __func__, + sqlite3_errmsg(ppDb) ); + } + + (void)sqlite3_close( ppDb ); + + return stream; +} + void writeToFile( XWStreamCtxt* stream, void* closure ) { @@ -414,6 +451,8 @@ typedef enum { ,CMD_SEED ,CMD_GAMESEED ,CMD_GAMEFILE + ,CMD_GAMEDB_FILE + ,CMD_GAMEDB_ID ,CMD_NOMMAP ,CMD_PRINTHISORY ,CMD_SKIPWARNINGS @@ -501,6 +540,8 @@ static CmdInfoRec CmdInfoRecs[] = { ,{ CMD_SEED, true, "seed", "random seed" } ,{ CMD_GAMESEED, true, "game-seed", "game seed (for relay play)" } ,{ CMD_GAMEFILE, true, "file", "file to save to/read from" } + ,{ CMD_GAMEDB_FILE, true, "game-db-file", "sqlite3 file, android format, holding game" } + ,{ CMD_GAMEDB_ID, true, "game-db-id", "id of row of game we want (defaults to first)" } ,{ CMD_NOMMAP, false, "no-mmap", "copy dicts to memory rather than mmap them" } ,{ CMD_PRINTHISORY, false, "print-history", "print history on game over" } ,{ CMD_SKIPWARNINGS, false, "skip-warnings", "no modals on phonies" } @@ -1452,6 +1493,11 @@ main( int argc, char** argv ) case CMD_GAMEFILE: mainParams.fileName = optarg; break; + case CMD_GAMEDB_FILE: + mainParams.dbFileName = optarg; + case CMD_GAMEDB_ID: + mainParams.dbFileID = atoi(optarg); + break; case CMD_NOMMAP: mainParams.useMmap = false; break; @@ -1675,7 +1721,7 @@ main( int argc, char** argv ) /* sanity checks */ totalPlayerCount = mainParams.nLocalPlayers + mainParams.info.serverInfo.nRemotePlayers; - if ( !mainParams.fileName ) { + if ( !mainParams.fileName && !mainParams.dbFileName ) { if ( (totalPlayerCount < 1) || (totalPlayerCount > MAX_NUM_PLAYERS) ) { mainParams.needsNewGame = XP_TRUE; diff --git a/xwords4/linux/linuxmain.h b/xwords4/linux/linuxmain.h index a5322a8a4..212c10e6b 100644 --- a/xwords4/linux/linuxmain.h +++ b/xwords4/linux/linuxmain.h @@ -64,6 +64,7 @@ void catFinalScores( const CommonGlobals* cGlobals ); XP_Bool file_exists( const char* fileName ); XWStreamCtxt* streamFromFile( CommonGlobals* cGlobals, char* name, void* closure ); +XWStreamCtxt* streamFromDB( CommonGlobals* cGlobals, void* closure ); void writeToFile( XWStreamCtxt* stream, void* closure ); int blocking_read( int fd, unsigned char* buf, int len ); diff --git a/xwords4/linux/main.h b/xwords4/linux/main.h index e9613444b..bf0bdefa4 100644 --- a/xwords4/linux/main.h +++ b/xwords4/linux/main.h @@ -49,6 +49,8 @@ typedef struct LaunchParams { CurGameInfo gi; PlayerDicts dicts; char* fileName; + char* dbFileName; + XP_U32 dbFileID; char* pipe; char* nbs; char* bonusFile;