### The object files (add further files here):
-OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o mvpclient.o tcp.o \
+OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o i18n.o mvpclient.o tcp.o \
ringbuffer.o mvprelay.o \
recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o \
media.o responsepacket.o
--- /dev/null
+/*
+ Copyright 2007 Mark Calderbank
+
+ This file is part of VOMP.
+
+ VOMP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "i18n.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <glob.h>
+
+using namespace std;
+
+I18n::I18n(char* tconfigDir)
+{
+ configDir = tconfigDir;
+}
+
+void I18n::findLanguages(void)
+{
+ glob_t globbuf;
+ char line[1000];
+
+ CodeList.clear();
+ FileList.clear();
+
+ string l10nGlob = configDir;
+ l10nGlob += "/l10n/*";
+ glob(l10nGlob.c_str(), 0, NULL, &globbuf);
+ for (unsigned int i=0; i < globbuf.gl_pathc; i++)
+ {
+ FILE *f = fopen(globbuf.gl_pathv[i], "r");
+ if (f)
+ {
+ while (fgets(line, 1000, f) && strncmp(line, "l10n-vomp:", 10) == 0)
+ {
+ string langline = line;
+ string code, name;
+
+ string::size_type pos_start, pos_end;
+ pos_start = langline.find_first_not_of(" \t\r\n", 10);
+ if (pos_start == string::npos) break;
+ pos_end = langline.find_first_of(" \t", pos_start);
+ if (pos_end == string::npos) break;
+ code = langline.substr(pos_start, pos_end - pos_start);
+ pos_start = langline.find_first_not_of(" \t\r\n", pos_end);
+ if (pos_start == string::npos) break;
+ pos_end = langline.find_last_not_of(" \t\r\n");
+ name = langline.substr(pos_start, pos_end + 1 - pos_start);
+ CodeList[code] = name;
+ FileList.insert(lang_file(code, globbuf.gl_pathv[i]));
+ }
+ fclose(f);
+ }
+ }
+ globfree(&globbuf);
+}
+
+I18n::trans_table I18n::getLanguageContent(const string code)
+{
+ trans_table Translations;
+ if (CodeList.count(code) == 0) return Translations;
+ LanguageCode = code;
+
+ pair<lang_file_list::const_iterator, lang_file_list::const_iterator> range;
+ range = FileList.equal_range(code);
+ lang_file_list::const_iterator iter;
+ for (iter = range.first; iter != range.second; ++iter)
+ {
+ FILE *f;
+ char line[1000];
+ string key;
+ f = fopen((*iter).second.c_str(), "r");
+ if (f)
+ {
+ while (fgets(line, 1000, f))
+ {
+ int linetype = 0;
+ string::size_type offset = 0;
+ string fileline = line;
+ if (fileline.compare(0, 2, "x:") == 0)
+ { // New key to be translated
+ linetype = 1; offset = 2;
+ }
+ if (fileline.compare(0, code.size() + 1, code + ":") == 0)
+ { // Translation for previous key
+ if (key.empty()) continue; // Translation without preceding key
+ linetype = 2; offset = code.size() + 1;
+ }
+ if (linetype != 0)
+ {
+ string::size_type start, end;
+ start = fileline.find_first_not_of(" \t\r\n",offset);
+ if (start == string::npos)
+ {
+ if (linetype == 2) Translations[key].clear();
+ continue;
+ }
+ end = fileline.find_last_not_of(" \t\r\n");
+ string text = fileline.substr(start, end + 1 - start);
+ if (text.length() > 1) // Strip quotes if at both ends
+ {
+ if (text[0] == '"' && text[text.length()-1] == '"')
+ text = text.substr(1, text.length()-2);
+ }
+ if (linetype == 1) key = text;
+ if (linetype == 2) Translations[key] = text;
+ }
+ }
+ fclose(f);
+ }
+ }
+ return Translations;
+}
+
+const I18n::lang_code_list& I18n::getLanguageList(void)
+{
+ return CodeList;
+}
--- /dev/null
+/*
+ Copyright 2007 Mark Calderbank
+
+ This file is part of VOMP.
+
+ VOMP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef I18N_H
+#define I18N_H
+
+#include <string>
+#include <map>
+
+class I18n
+{
+ public:
+ I18n(char* tconfigDir);
+ typedef std::map<std::string,std::string> lang_code_list;
+ typedef std::pair<std::string,std::string> lang_code;
+ typedef std::map<std::string,std::string> trans_table;
+ typedef std::pair<std::string,std::string> trans_entry;
+
+ void findLanguages(void);
+ trans_table getLanguageContent(const std::string code);
+ const lang_code_list& getLanguageList(void);
+
+ private:
+ char* configDir;
+ std::string LanguageCode;
+ lang_code_list CodeList;
+
+ typedef std::multimap<std::string,std::string> lang_file_list;
+ typedef std::pair<std::string,std::string> lang_file;
+ lang_file_list FileList;
+};
+#endif
MVPClient::MVPClient(Config* cfgBase, char* tconfigDir, int tsocket)
- : tcp(tsocket)
+ : tcp(tsocket), i18n(tconfigDir)
{
#ifndef VOMPSTANDALONE
lp = NULL;
log = Log::getInstance();
loggedIn = false;
configDir = tconfigDir;
+ log->log("Client", Log::DEBUG, "Config dir: %s", configDir);
baseConfig = cfgBase;
incClients();
}
case 32:
result = processGetImageBlock(data, extraDataLength, rp);
break;
+ case 33:
+ result = processGetLanguageList(data, extraDataLength, rp);
+ break;
+ case 34:
+ result = processGetLanguageContent(data, extraDataLength, rp);
+ break;
}
if (data) free(data);
}
+int MVPClient::processGetLanguageList(UCHAR* data, int length, ResponsePacket* rp)
+{
+ i18n.findLanguages();
+ const I18n::lang_code_list& languages = i18n.getLanguageList();
+ std::string result;
+ I18n::lang_code_list::const_iterator iter;
+ for (iter = languages.begin(); iter != languages.end(); ++iter)
+ {
+ rp->addString(iter->first.c_str());
+ rp->addString(iter->second.c_str());
+ }
+ rp->finalise();
+ tcp.sendPacket(rp->getPtr(), rp->getLen());
+ delete rp;
+ return 1;
+}
+
+int MVPClient::processGetLanguageContent(UCHAR* data, int length, ResponsePacket* rp)
+{
+ if (length <= 0) return 0;
+ std::string code, result;
+ code.assign((char*)data, length - 1);
+ i18n.findLanguages();
+ I18n::trans_table texts = i18n.getLanguageContent(code);
+ I18n::trans_table::const_iterator iter;
+ for (iter = texts.begin(); iter != texts.end(); ++iter)
+ {
+ rp->addString(iter->first.c_str());
+ rp->addString(iter->second.c_str());
+ }
+ rp->finalise();
+ tcp.sendPacket(rp->getPtr(), rp->getLen());
+ delete rp;
+ return 1;
+}
+
+
+
+
+
#include "tcp.h"
#include "config.h"
#include "media.h"
+#include "i18n.h"
class ResponsePacket;
TCP tcp;
Config config;
Config* baseConfig;
+ I18n i18n;
bool loggedIn;
char* configDir;
FILE* imageFile;
int processGetMediaList(UCHAR* data, int length, ResponsePacket* rp);
int processGetPicture(UCHAR* data, int length, ResponsePacket* rp);
int processGetImageBlock(UCHAR* data, int length, ResponsePacket* rp);
+ int processGetLanguageList(UCHAR* data, int length, ResponsePacket* rp);
+ int processGetLanguageContent(UCHAR* data, int length, ResponsePacket* rp);
void incClients();
void decClients();