svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/Workspace.cpp
Go to the documentation of this file.
00001 #include <Poco/AutoPtr.h>
00002 #include <Poco/DOM/DOMParser.h>
00003 #include <Poco/DOM/Document.h>
00004 #include <Poco/DOM/Element.h>
00005 #include <Poco/DOM/NodeList.h>
00006 #include <Poco/DOM/DOMWriter.h>
00007 #include <Poco/XML/XMLWriter.h>
00008 #include <Poco/DateTime.h>
00009 #include <Poco/DateTimeFormat.h>
00010 #include <Poco/DateTimeParser.h>
00011 #include <Poco/Timezone.h>
00012 #include <Poco/Exception.h>
00013 #include <Poco/FileStream.h>
00014 #include <Poco/format.h>
00015 #include <Poco/hash.h>
00016 #include <Poco/string.h>
00017 #include <Poco/UnicodeConverter.h>
00018 
00019 #include "Workspace.h"
00020 #include "Utils.h"
00021 
00022 using Poco::XML::Document;
00023 using Poco::XML::Element;
00024 using Poco::XML::NodeList;
00025 
00026 
00027 Workspace::Workspace(Path file): _log(Poco::Logger::get("")), _file(file) {
00028 }
00029 
00030 Workspace::‾Workspace() {
00031     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00032     release();
00033 }
00034 
00035 
00036 void Workspace::release() {
00037     for (vector<SchedulePtr>::iterator it = _schedule.begin(); it != _schedule.end(); it++) {
00038         SAFE_DELETE(*it);
00039     }
00040     for (vector<PlayListPtr>::iterator it = _playlist.begin(); it != _playlist.end(); it++) {
00041         PlayListPtr playlist = *it;
00042         // _renderer.removeCachedTexture(playlist->name());
00043         SAFE_DELETE(playlist);
00044     }
00045     _playlistMap.clear();
00046     _playlist.clear();
00047 
00048     for (vector<MediaItemPtr>::iterator it = _media.begin(); it != _media.end(); it++) {
00049         MediaItemPtr media = *it;
00050 //      _renderer.removeCachedTexture(media->id());
00051         SAFE_DELETE(media);
00052     }
00053     _mediaMap.clear();
00054     _media.clear();
00055     _log.information("release workspace");
00056 }
00057 
00058 const Path& Workspace::file() const {
00059     return _file;
00060 }
00061 
00062 bool Workspace::checkUpdate() {
00063     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00064     string signature = svvitch::md5(_file.toString());
00065     if (_signature != signature) {
00066         _log.information(Poco::format("detect update workspace: %s", _signature));
00067         return true;
00068     }
00069     return false;
00070 }
00071 
00072 bool Workspace::parse() {
00073     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00074     try {
00075         string signature = svvitch::md5(_file);
00076         Poco::XML::DOMParser parser;
00077         Document* doc = parser.parse(_file.toString());
00078         if (doc) {
00079             _log.information(Poco::format("update/parse workspace file: %s", _file.toString()));
00080             release();
00081             NodeList* nodes = doc->documentElement()->getElementsByTagName("medialist");
00082             if (nodes) {
00083                 _media.clear();
00084                 _existsFiles.clear();
00085                 for (int i = 0; i < nodes->length(); i++) {
00086                     Element* e = (Element*)nodes->item(i);
00087                     NodeList* items = e->getElementsByTagName("item");
00088                     for (int j = 0; j < items->length(); j++) {
00089                         e = (Element*)items->item(j);
00090                         string type = Poco::toLower(e->getAttribute("type"));
00091                         string name = e->getAttribute("name");
00092                         string id = e->getAttribute("id");
00093                         string s = e->getAttribute("start");
00094                         int start = 0;
00095                         if (!s.empty()) {
00096                             start = Poco::NumberParser::parse(s);
00097                         }
00098                         string d = e->getAttribute("duration");
00099                         int duration = 0;
00100                         if (!d.empty()) {
00101                             duration = Poco::NumberParser::parse(d);
00102                         }
00103                         string parameters = e->getAttribute("params");
00104                         vector<MediaItemFile> files;
00105                         NodeList* movies = e->getElementsByTagName("*");
00106                         for (int k = 0; k < movies->length(); k++) {
00107                             e = (Element*)movies->item(k);
00108                             string file = e->innerText();
00109                             if (file.find("switch-data:/") == 0) {
00110                                 file = Path(config().dataRoot, file.substr(13)).toString();
00111                             }
00112                             string params;
00113                             if (file.find("?") != string::npos) {
00114                                 params = file.substr(file.find("?") + 1);
00115                                 file = file.substr(0, file.find("?"));
00116                             }
00117                             if (e->tagName() == "movie") {
00118                                 files.push_back(MediaItemFile(MediaTypeMovie, file, params));
00119                             } else if (e->tagName() == "image") {
00120                                 files.push_back(MediaItemFile(MediaTypeImage, file, params));
00121                             } else if (e->tagName() == "text") {
00122                                 files.push_back(MediaItemFile(MediaTypeText, file, params));
00123                             } else if (e->tagName() == "flash") {
00124                                 files.push_back(MediaItemFile(MediaTypeFlash, file, params));
00125                             } else {
00126                                 files.push_back(MediaItemFile(MediaTypeUnknown, file, params));
00127                             }
00128                         }
00129                         movies->release();
00130 
00131                         MediaType typeCode = MediaTypeUnknown;
00132                         if (type == "mix") {
00133                             typeCode = MediaTypeMix;
00134                         } else if (type == "movie") {
00135                             typeCode = MediaTypeMovie;
00136                         } else if (type == "image") {
00137                             typeCode = MediaTypeImage;
00138                         } else  if (type == "flash") {
00139                             typeCode = MediaTypeFlash;
00140                         } else  if (type == "browser") {
00141                             typeCode = MediaTypeBrowser;
00142                         } else  if (type == "cv") {
00143                             typeCode = MediaTypeCv;
00144                         } else  if (type == "cvcap") {
00145                             typeCode = MediaTypeCvCap;
00146                         } else  if (type == "game") {
00147                             typeCode = MediaTypeGame;
00148                         } else  if (type == "game2") {
00149                             typeCode = MediaTypeGame2;
00150                         }
00151                         Poco::HashMap<string, MediaItemPtr>::Iterator find = _mediaMap.find(id);
00152                         if (find != _mediaMap.end()) {
00153                             _log.warning(Poco::format("already registed media, delete old item: %s", id));
00154                             for (vector<MediaItemPtr>::iterator it = _media.begin(); it != _media.end(); it++) {
00155                                 MediaItemPtr media = *it;
00156                                 if (id == media->id()) {
00157                                     _media.erase(it);
00158                                     break;
00159                                 }
00160                             }
00161                             SAFE_DELETE(find->second);
00162                             _mediaMap.erase(find);
00163                         }
00164                         MediaItemPtr media  = new MediaItem(typeCode, id, name, start, duration, parameters, files);
00165                         _mediaMap[id] = media;
00166                         _media.push_back(media);
00167                         switch (media->type()) {
00168                         case MediaTypeMix:
00169                         case MediaTypeMovie:
00170                         case MediaTypeImage:
00171                         case MediaTypeText:
00172                         case MediaTypeFlash:
00173                             for (vector<MediaItemFile>::const_iterator it = files.begin(); it != files.end(); it++) {
00174                                 if (!((*it).file().empty()) && (*it).file().find("http") == string::npos) {
00175                                     try {
00176                                         File f = File((*it).file());
00177                                         if (f.exists()) _existsFiles.push_back(f.path());
00178                                     } catch (Poco::FileException& ex) {
00179                                     }
00180                                 }
00181                             }
00182                         }
00183                     }
00184                     items->release();
00185                 }
00186                 nodes->release();
00187             }
00188             _log.information(Poco::format("media item: %?u", _media.size()));
00189 
00190             nodes = doc->documentElement()->getElementsByTagName("playlists");
00191             if (nodes) {
00192                 for (int i = 0; i < nodes->length(); i++) {
00193                     Element* e = (Element*)nodes->item(i);
00194                     NodeList* nodesPlaylist = e->getElementsByTagName("playlist");
00195                     for (int j = 0; j < nodesPlaylist->length(); j++) {
00196                         e = (Element*)nodesPlaylist->item(j);
00197                         string name = e->getAttribute("name");
00198                         string id = e->getAttribute("id");
00199                         if (id.empty()) {
00200                             // TODO playlist.id指定が無い時の処理
00201                             id = Poco::format("g%04d", j);
00202 //                          _log.information(Poco::format("auto group id: %s", id));
00203                         }
00204                         string text = e->getAttribute("text");
00205                         PlayListPtr playlist = new PlayList(id, name, text);
00206                         NodeList* items = e->getElementsByTagName("item");
00207                         for (int k = 0; k < items->length(); k++) {
00208                             e = (Element*)items->item(k);
00209                             string id = e->innerText();
00210                             string next = e->getAttribute("next");
00211                             string transition = e->getAttribute("transition");
00212                             Poco::HashMap<string, MediaItemPtr>::Iterator it = _mediaMap.find(id);
00213                             if (it != _mediaMap.end()) {
00214                                 playlist->add(new PlayListItem(it->second, next, transition));
00215                             } else {
00216                                 _log.warning(Poco::format("not found item[id:%s] in playlist[name:%s]", id, name));
00217                             }
00218                         }
00219                         _playlistMap[id] = playlist;
00220                         _playlist.push_back(playlist);
00221 //                      _log.debug(Poco::format("playlist: %s x%d", playlist->name(), playlist->itemCount()));
00222                         items->release();
00223                     }
00224                     nodesPlaylist->release();
00225                 }
00226                 nodes->release();
00227             }
00228             _log.information(Poco::format("playlist: %?u", _playlist.size()));
00229 
00230             nodes = doc->documentElement()->getElementsByTagName("schedule");
00231             if (nodes) {
00232                 for (int i = 0; i < nodes->length(); i++) {
00233                     Element* schedule = (Element*)nodes->item(i);
00234                     NodeList* items = schedule->getElementsByTagName("item");
00235                     for (int j = 0; j < items->length(); j++) {
00236                         Element* e = (Element*)items->item(j);
00237                         string id = e->getAttribute("id");
00238                         string t = e->getAttribute("time");
00239                         string command = e->innerText();
00240                         vector<int> time = svvitch::parseTimes(t);
00241                         if (time.size() == 7) {
00242                             SchedulePtr schedule = new Schedule(id, time[0], time[1], time[2], time[3], time[4], time[5], time[6], command);
00243                             _schedule.push_back(schedule);
00244                         } else if (time.size() == 6) {
00245                             // spec of old
00246                             SchedulePtr schedule = new Schedule(id, time[0], time[1], time[2], time[3], time[4], 0, time[5], command);
00247                             _schedule.push_back(schedule);
00248                         }
00249                     }
00250                     items->release();
00251                 }
00252                 nodes->release();
00253             }
00254 
00255             nodes = doc->documentElement()->getElementsByTagName("fonts");
00256             if (nodes) {
00257                 for (int i = 0; i < nodes->length(); i++) {
00258                     Element* fonts = (Element*)nodes->item(i);
00259                     NodeList* files = fonts->getElementsByTagName("file");
00260                     for (int j = 0; j < files->length(); j++) {
00261                         Element* e = (Element*)files->item(j);
00262                         string path = e->innerText();
00263                         if (path.find("switch-data:/") == 0) {
00264                             Path p(config().dataRoot, path.substr(13));
00265                             path = p.parse(p.toString()).toString();
00266                         }
00267                         _fonts.push_back(path);
00268                     }
00269                 }
00270             }
00271             doc->release();
00272             _signature = signature;
00273             return true;
00274         } else {
00275             _log.warning(Poco::format("failed parse: %s", _file));
00276         }
00277     } catch (Poco::Exception& ex) {
00278         _log.warning(ex.displayText());
00279     }
00280     return false;
00281 }
00282 
00283 const int Workspace::getMediaCount() {
00284     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00285     return _media.size();
00286 }
00287 
00288 const MediaItemPtr Workspace::getMedia(int i) {
00289     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00290     if (i >= 0 && i < _media.size()) {
00291         return _media[i];
00292     }
00293     return NULL;
00294 }
00295 
00296 const MediaItemPtr Workspace::getMedia(string id) {
00297     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00298     Poco::HashMap<string, MediaItemPtr>::Iterator it = _mediaMap.find(id);
00299     if (it != _mediaMap.end()) {
00300         return it->second;
00301     }
00302     return NULL;
00303 }
00304 
00305 
00306 const int Workspace::getPlaylistCount() {
00307     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00308     return _playlist.size();
00309 }
00310 
00311 const PlayListPtr Workspace::getPlaylist(int i) {
00312     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00313     if (i >= 0 && i < _playlist.size()) {
00314         return _playlist[i];
00315     }
00316     return NULL;
00317 }
00318 
00319 const PlayListPtr Workspace::getPlaylist(string id) {
00320     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00321     Poco::HashMap<string, PlayListPtr>::Iterator it = _playlistMap.find(id);
00322     if (it != _playlistMap.end()) {
00323         return it->second;
00324     }
00325     return NULL;
00326 }
00327 
00328 const vector<string> Workspace::getFonts() {
00329     return _fonts;
00330 }
00331 
00332 const int Workspace::getScheduleCount() {
00333     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00334     return _schedule.size();
00335 }
00336 
00337 const SchedulePtr Workspace::getSchedule(int i) {
00338     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00339     if (i >= 0 && i < _schedule.size()) {
00340         return _schedule[i];
00341     }
00342     return NULL;
00343 }
00344 
00345 const vector<string> Workspace::existsFiles() {
00346     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00347     return _existsFiles;
00348 }
00349 
00350 const string Workspace::signature() const {
00351     return _signature;
00352 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines