From d0302f7889dabc2d2fc525b5797d66df2c0a4b23 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Tue, 31 Mar 2009 11:22:24 +0000 Subject: [PATCH] DSM actions to handle files in database git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1346 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/dsm/DSMSession.h | 11 +- apps/dsm/doc/examples/test_dbfile.dsm | 15 ++ apps/dsm/mods/mod_mysql/ModMysql.cpp | 151 ++++++++++++++++++ apps/dsm/mods/mod_mysql/ModMysql.h | 5 +- .../dsm/mods/mod_mysql/Readme.mod_mysqlpp.txt | 19 ++- 5 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 apps/dsm/doc/examples/test_dbfile.dsm diff --git a/apps/dsm/DSMSession.h b/apps/dsm/DSMSession.h index 507253a7..984807bd 100644 --- a/apps/dsm/DSMSession.h +++ b/apps/dsm/DSMSession.h @@ -30,6 +30,7 @@ #include "AmArg.h" #include "AmEvent.h" #include "AmSipMsg.h" +#include "AmAudioFile.h" #include using std::string; @@ -100,13 +101,21 @@ class DSMSession { }; - class DSMDisposable { public: DSMDisposable() { } virtual ~DSMDisposable() { } }; +class DSMDisposableAudioFile +: public DSMDisposable, + public AmAudioFile +{ + public: + DSMDisposableAudioFile() { } + ~DSMDisposableAudioFile() { } +}; + #define DSM_EVENT_ID -10 /** generic event for passing events between DSM sessions */ struct DSMEvent : public AmEvent { diff --git a/apps/dsm/doc/examples/test_dbfile.dsm b/apps/dsm/doc/examples/test_dbfile.dsm new file mode 100644 index 00000000..078f2341 --- /dev/null +++ b/apps/dsm/doc/examples/test_dbfile.dsm @@ -0,0 +1,15 @@ +import(mod_mysql); + +initial state lobby + enter { + mysql.connect(mysql://root:sa07@localhost/sems); + mysql.putFileToDB('INSERT INTO audio (application,message,audio) VALUES ("test","testmessage","__FILE__")', wav/welcome.wav); + mysql.playDBAudio(SELECT audio FROM audio WHERE id=$db.insert_id, anything.wav); + mysql.getFileFromDB(SELECT audio FROM audio WHERE id=$db.insert_id, /tmp/retrieved.wav); + }; + +transition "error" lobby - test($errno!="") / stop(true) -> end; +transition "audio ends" lobby - noAudioTest / stop(true) -> end; +transition "bye recvd" lobby - hangup / stop(false) -> end; + +state end; \ No newline at end of file diff --git a/apps/dsm/mods/mod_mysql/ModMysql.cpp b/apps/dsm/mods/mod_mysql/ModMysql.cpp index d732b348..808dd4aa 100644 --- a/apps/dsm/mods/mod_mysql/ModMysql.cpp +++ b/apps/dsm/mods/mod_mysql/ModMysql.cpp @@ -31,6 +31,10 @@ #include "DSMSession.h" #include "AmSession.h" +#include "AmPlaylist.h" + +#include +#include SC_EXPORT(SCMysqlModule); @@ -56,6 +60,9 @@ DSMAction* SCMysqlModule::getAction(const string& from_str) { DEF_CMD("mysql.resolveQueryParams", SCMyResolveQueryParams); DEF_CMD("mysql.saveResult", SCMySaveResultAction); DEF_CMD("mysql.useResult", SCMyUseResultAction); + DEF_CMD("mysql.playDBAudio", SCMyPlayDBAudioAction); + DEF_CMD("mysql.getFileFromDB", SCMyGetFileFromDBAction); + DEF_CMD("mysql.putFileToDB", SCMyPutFileToDBAction); return NULL; } @@ -417,3 +424,147 @@ EXEC_ACTION_START(SCMySaveResultAction) { EXEC_ACTION_START(SCMyUseResultAction) { sc_sess->avar[MY_AKEY_RESULT] = sc_sess->avar[resolveVars(arg, sess, sc_sess, event_params)]; } EXEC_ACTION_END; + + +CONST_ACTION_2P(SCMyPlayDBAudioAction, ',', true); +EXEC_ACTION_START(SCMyPlayDBAudioAction) { + mysqlpp::Connection* conn = + getMyDSMSessionConnection(sc_sess); + if (NULL == conn) + return false; + string qstr = replaceQueryParams(par1, sc_sess, event_params); + + try { + mysqlpp::Query query = conn->query(qstr.c_str()); + mysqlpp::UseQueryResult res = query.use(); + if (res) { + + mysqlpp::Row row = res.fetch_row(); + if (!row) { + sc_sess->SET_ERRNO(DSM_ERRNO_MY_NOROW); + return false; + } + FILE *t_file = tmpfile(); + if (NULL == t_file) { + sc_sess->SET_ERRNO(DSM_ERRNO_FILE); + return false; + } + + fwrite(row.at(0).data(), 1, row.at(0).size(), t_file); + rewind(t_file); + + DSMDisposableAudioFile* a_file = new DSMDisposableAudioFile(); + if (a_file->fpopen(par2, AmAudioFile::Read, t_file)) { + sc_sess->SET_ERRNO(DSM_ERRNO_FILE); + return false; + } + + sc_sess->addToPlaylist(new AmPlaylistItem(a_file, NULL)); + sc_sess->transferOwnership(a_file); + + sc_sess->SET_ERRNO(DSM_ERRNO_OK); + } else { + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + } + } catch (const mysqlpp::Exception& e) { + ERROR("DB query '%s' failed: '%s'\n", + qstr.c_str(), e.what()); + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + sc_sess->var["db.ereason"] = e.what(); + } +} EXEC_ACTION_END; + +CONST_ACTION_2P(SCMyGetFileFromDBAction, ',', true); +EXEC_ACTION_START(SCMyGetFileFromDBAction) { + mysqlpp::Connection* conn = + getMyDSMSessionConnection(sc_sess); + if (NULL == conn) + return false; + string qstr = replaceQueryParams(par1, sc_sess, event_params); + + try { + mysqlpp::Query query = conn->query(qstr.c_str()); + mysqlpp::UseQueryResult res = query.use(); + if (res) { + mysqlpp::Row row = res.fetch_row(); + if (!row) { + sc_sess->SET_ERRNO(DSM_ERRNO_MY_NOROW); + return false; + } + FILE *t_file = fopen(par2.c_str(), "wb"); + if (NULL == t_file) { + sc_sess->SET_ERRNO(DSM_ERRNO_FILE); + return false; + } + + fwrite(row.at(0).data(), 1, row.at(0).size(), t_file); + fclose(t_file); + + sc_sess->SET_ERRNO(DSM_ERRNO_OK); + } else { + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + } + } catch (const mysqlpp::Exception& e) { + ERROR("DB query '%s' failed: '%s'\n", + qstr.c_str(), e.what()); + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + sc_sess->var["db.ereason"] = e.what(); + } +} EXEC_ACTION_END; + +CONST_ACTION_2P(SCMyPutFileToDBAction, ',', true); +EXEC_ACTION_START(SCMyPutFileToDBAction) { + mysqlpp::Connection* conn = + getMyDSMSessionConnection(sc_sess); + if (NULL == conn) + return false; + string qstr = replaceQueryParams(par1, sc_sess, event_params); + + size_t fpos = qstr.find("__FILE__"); + if (fpos == string::npos) { + ERROR("missing __FILE__ in query string '%s'\n", + par1.c_str()); + sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); + return false; + } + + try { + std::ifstream data_file(par2.c_str(), std::ios::in | std::ios::binary); + if (!data_file) { + DBG("could not read file '%s'\n", par2.c_str()); + sc_sess->SET_ERRNO(DSM_ERRNO_FILE); + return false; + } + // that one is clever... + // (see http://www.gamedev.net/community/forums/topic.asp?topic_id=353162 ) + string file_data((std::istreambuf_iterator(data_file)), + std::istreambuf_iterator()); + + if (file_data.empty()) { + DBG("could not read file '%s'\n", par2.c_str()); + sc_sess->SET_ERRNO(DSM_ERRNO_FILE); + return false; + } + + mysqlpp::Query query = conn->query(); + query << qstr.substr(0, fpos) << + mysqlpp::escape << file_data << qstr.substr(fpos+8); + + mysqlpp::SimpleResult res = query.execute(); + if (res) { + sc_sess->SET_ERRNO(DSM_ERRNO_OK); + sc_sess->var["db.rows"] = int2str(res.rows()); + sc_sess->var["db.info"] = res.info(); + sc_sess->var["db.insert_id"] = int2str(res.insert_id()); + } else { + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + sc_sess->var["db.info"] = res.info(); + } + + } catch (const mysqlpp::Exception& e) { + ERROR("DB query '%s' failed: '%s'\n", + par1.c_str(), e.what()); + sc_sess->SET_ERRNO(DSM_ERRNO_MY_QUERY); + sc_sess->var["db.ereason"] = e.what(); + } +} EXEC_ACTION_END; diff --git a/apps/dsm/mods/mod_mysql/ModMysql.h b/apps/dsm/mods/mod_mysql/ModMysql.h index 78be9076..1435a62d 100644 --- a/apps/dsm/mods/mod_mysql/ModMysql.h +++ b/apps/dsm/mods/mod_mysql/ModMysql.h @@ -87,7 +87,8 @@ DEF_SCCondition(MyHasResultCondition); DEF_SCCondition(MyConnectedCondition); DEF_ACTION_1P(SCMySaveResultAction); DEF_ACTION_1P(SCMyUseResultAction); - - +DEF_ACTION_2P(SCMyPlayDBAudioAction); +DEF_ACTION_2P(SCMyGetFileFromDBAction); +DEF_ACTION_2P(SCMyPutFileToDBAction); #endif diff --git a/apps/dsm/mods/mod_mysql/Readme.mod_mysqlpp.txt b/apps/dsm/mods/mod_mysql/Readme.mod_mysqlpp.txt index 73e0cebd..036cc29d 100644 --- a/apps/dsm/mods/mod_mysql/Readme.mod_mysqlpp.txt +++ b/apps/dsm/mods/mod_mysql/Readme.mod_mysqlpp.txt @@ -82,8 +82,23 @@ Actions: -- save result into another name mysql.saveResult(string name) --- user saved result - mysql.userResult(string name) +-- use saved result + mysql.useResult(string name) + +-- play a file from DB + mysql.playDBAudio(string query, string filename) + + filename is there to detect file type + +-- get a file from DB to local fs + mysql.getFileFromDB(string query, string filename) + +-- put a local file into DB + mysql.putFileToDB(string query, string filename) + + __FILE__ in query is replaced with the contents of the file at 'filename' + + sets $db.rows, $db.info, $db.insert_id Conditions ==========