diff options
Diffstat (limited to 'database')
-rw-r--r-- | database/database.h | 4 | ||||
-rw-r--r-- | database/metadata.cpp | 104 | ||||
-rw-r--r-- | database/object.cpp | 214 | ||||
-rw-r--r-- | database/object.h | 12 | ||||
-rw-r--r-- | database/resources.cpp | 26 |
5 files changed, 312 insertions, 48 deletions
diff --git a/database/database.h b/database/database.h index 49c208d..24e8bd1 100644 --- a/database/database.h +++ b/database/database.h @@ -12,8 +12,8 @@ #include <vdr/tools.h> #include "../common.h" -#define SQLITE_PRINT_STATEMENTS -#define SQLITE_PRINT_FETCHES +//#define SQLITE_PRINT_STATEMENTS +//#define SQLITE_PRINT_FETCHES #define SQLITE_CASCADE_DELETES #define PK_OBJECTS TOSTRING(1) diff --git a/database/metadata.cpp b/database/metadata.cpp index 438d002..6966602 100644 --- a/database/metadata.cpp +++ b/database/metadata.cpp @@ -52,10 +52,10 @@ bool cMediaDatabase::init(){ ERROR("Loading channels failed"); return false; } -// if(this->loadRecordings()){ -// ERROR("Loading records failed"); -// return false; -// } + if(this->loadRecordings()){ + ERROR("Loading records failed"); + return false; + } return true; } @@ -315,43 +315,65 @@ int cMediaDatabase::loadChannels(){ return 0; } -//int cMediaDatabase::loadRecordings(){ -// MESSAGE("Loading recordings"); -// cUPnPClassContainer* Records = (cUPnPClassContainer*)this->getObjectByID(4); -// if(Records){ -// cRecording* Recording = NULL; -// for(Recording = Recordings.First(); Recording; Recording = Recordings.Next(Recording)){ -// // Iterating the records -// bool inList = false; -// -// MESSAGE("Determine if the channel %s is already listed", Recording->FileName()); -// const cRecordingInfo* RecInfo = Recording->Info(); -// -// MESSAGE("%s", *RecInfo->Components()->Component(0)->ToString()); -// cUPnPClassMovie *MovieItem = NULL; -// -// MovieItem = (cUPnPClassMovie*)this->getObjectByFastFind(Recording->FileName()); -// -// inList = (MovieItem && Records->getObject(MovieItem->getID())) ? true : false; -// -// if(inList){ -// -// MESSAGE("Adding movie '%s' File name:%s", RecInfo->Title(), Recording->FileName()); -// -// MovieItem = (cUPnPClassMovie*)this->mFactory->createObject(UPNP_CLASS_MOVIE, RecInfo->Title()); -// MovieItem->setDescription(RecInfo->ShortText()); -// MovieItem->setLongDescription(RecInfo->Description()); -// MovieItem->setStorageMedium(UPNP_STORAGE_HDD); -// -// -// } -// else { -// MESSAGE("Skipping %s, already in Database", Recording->FileName()); -// } -// } -// } -// return 0; -//} +int cMediaDatabase::loadRecordings(){ + MESSAGE("Loading recordings"); + cUPnPClassContainer* Records = (cUPnPClassContainer*)this->getObjectByID(4); + if(Records){ + bool noResource = false; + // TODO: Add to setup + // if an error occured while loading resources, add the channel anyway + bool addWithoutResources = false; + cRecording* Recording = NULL; + for(Recording = Recordings.First(); Recording; Recording = Recordings.Next(Recording)){ + // Iterating the records + bool inList = false; + + MESSAGE("Determine if the channel %s is already listed", Recording->FileName()); + + cUPnPClassMovie *MovieItem = NULL; + + MovieItem = (cUPnPClassMovie*)this->getObjectByFastFind(Recording->FileName()); + + inList = (MovieItem && Records->getObject(MovieItem->getID())) ? true : false; + + if(inList){ + noResource = false; + const cRecordingInfo* RecInfo = Recording->Info(); + + MESSAGE("Adding movie '%s' File name:%s", RecInfo->Title(), Recording->FileName()); + + MovieItem = (cUPnPClassMovie*)this->mFactory->createObject(UPNP_CLASS_MOVIE, RecInfo->Title()); + MovieItem->setDescription(RecInfo->ShortText()); + MovieItem->setLongDescription(RecInfo->Description()); + MovieItem->setStorageMedium(UPNP_STORAGE_HDD); + + if(RecInfo->Components()){ + // The first component + tComponent *Component = RecInfo->Components()->Component(0); + if(Component) MovieItem->setLanguage(Component->language); + } + + if(cUPnPResources::getInstance()->createFromRecording(MovieItem, Recording)){ + ERROR("Unable to get resources for this channel"); + noResource = true; + } + if(!noResource || addWithoutResources) { + Records->addObject(MovieItem); + if(this->mFactory->saveObject(MovieItem) || + this->addFastFind(MovieItem, Recording->FileName())){ + this->mFactory->deleteObject(MovieItem); + return -1; + } + MESSAGE("Successfuly added movie"); + } + } + else { + MESSAGE("Skipping %s, already in Database", Recording->FileName()); + } + } + } + return 0; +} void cMediaDatabase::Action(){ time_t LastEPGUpdate = 0; diff --git a/database/object.cpp b/database/object.cpp index e533fbc..0587f6a 100644 --- a/database/object.cpp +++ b/database/object.cpp @@ -868,11 +868,125 @@ int cUPnPClassVideoBroadcast::setRegion(const char* Region){ return 0; } - /**********************************************\ - * * - * Mediator factory * - * * - \**********************************************/ +/**********************************************\ +* * +* Movie item * +* * +\**********************************************/ + +cUPnPClassMovie::cUPnPClassMovie(){ + this->mDVDRegionCode = 2; // Europe + this->mStorageMedium = UPNP_STORAGE_UNKNOWN; +} + +cUPnPClassMovie::~cUPnPClassMovie(){} + +//cString cUPnPClassMovie::createDIDLFragment(cStringList* Filter){ +// return NULL; +//} + +cStringList* cUPnPClassMovie::getPropertyList(){ + cStringList* Properties = cUPnPClassVideoItem::getPropertyList(); + Properties->Append(strdup(UPNP_PROP_DVDREGIONCODE)); + Properties->Append(strdup(UPNP_PROP_STORAGEMEDIUM)); + return Properties; +} + +bool cUPnPClassMovie::setProperty(const char* Property, const char* Value){ + bool ret; + if(!strcasecmp(Property, SQLITE_COL_DVDREGIONCODE) || !strcasecmp(Property, UPNP_PROP_DVDREGIONCODE)){ + ret = this->setDVDRegionCode(atoi(Value)); + } + else if(!strcasecmp(Property, SQLITE_COL_STORAGEMEDIUM) || !strcasecmp(Property, UPNP_PROP_STORAGEMEDIUM)){ + ret = this->setStorageMedium(Value); + } + else return cUPnPClassVideoItem::setProperty(Property, Value); + return ret<0?false:true; +} + +bool cUPnPClassMovie::getProperty(const char* Property, char** Value) const { + cString Val; + if(!strcasecmp(Property, SQLITE_COL_DVDREGIONCODE) || !strcasecmp(Property, UPNP_PROP_DVDREGIONCODE)){ + Val = itoa(this->getDVDRegionCode()); + } + else if(!strcasecmp(Property, SQLITE_COL_STORAGEMEDIUM) || !strcasecmp(Property, UPNP_PROP_STORAGEMEDIUM)){ + Val = this->getStorageMedium(); + } + else return cUPnPClassVideoItem::getProperty(Property, Value); + *Value = strdup0(*Val); + return true; +} + +int cUPnPClassMovie::setDVDRegionCode(int RegionCode){ +// http://en.wikipedia.org/wiki/DVD_region_code +// 0 Informal term meaning "worldwide". Region 0 is not an official setting; discs that bear the region 0 symbol either have no flag set or have region 1–6 flags set. +// 1 Canada, United States; U.S. territories; Bermuda +// 2 Western Europe; incl. United Kingdom, Ireland, and Central Europe; Eastern Europe, Western Asia; including Iran, Israel, Egypt; Japan, South Africa, Swaziland, Lesotho; French overseas territories +// 3 Southeast Asia; South Korea; Taiwan; Hong Kong; Macau +// 4 Mexico, Central and South America; Caribbean; Australia; New Zealand; Oceania; +// 5 Ukraine, Belarus, Russia, Continent of Africa, excluding Egypt, South Africa, Swaziland, and Lesotho; Central and South Asia, Mongolia, North Korea. +// 6 People's Republic of China +// 7 Reserved for future use (found in use on protected screener copies of MPAA-related DVDs and "media copies" of pre-releases in Asia) +// 8 International venues such as aircraft, cruise ships, etc.[1] +// ALL (9) Region ALL discs have all 8 flags set, allowing the disc to be played in any locale on any player. + if(0 <= RegionCode && RegionCode <= 9){ + this->mDVDRegionCode = RegionCode; + return 0; + } + else { + ERROR("Invalid DVD region code: %d", RegionCode); + return -1; + } +} + +int cUPnPClassMovie::setStorageMedium(const char* StorageMedium){ + if(!StorageMedium) this->mStorageMedium = UPNP_STORAGE_UNKNOWN; + else if( + strcasecmp(StorageMedium,UPNP_STORAGE_CD_DA) || + strcasecmp(StorageMedium,UPNP_STORAGE_CD_R) || + strcasecmp(StorageMedium,UPNP_STORAGE_CD_ROM) || + strcasecmp(StorageMedium,UPNP_STORAGE_CD_RW) || + strcasecmp(StorageMedium,UPNP_STORAGE_DAT) || + strcasecmp(StorageMedium,UPNP_STORAGE_DV) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_AUDIO) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_RAM) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_ROM) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_RW_MINUS) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_RW_PLUS) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_R_MINUS) || + strcasecmp(StorageMedium,UPNP_STORAGE_DVD_VIDEO) || + strcasecmp(StorageMedium,UPNP_STORAGE_D_VHS) || + strcasecmp(StorageMedium,UPNP_STORAGE_HDD) || + strcasecmp(StorageMedium,UPNP_STORAGE_HI8) || + strcasecmp(StorageMedium,UPNP_STORAGE_LD) || + strcasecmp(StorageMedium,UPNP_STORAGE_MD_AUDIO) || + strcasecmp(StorageMedium,UPNP_STORAGE_MD_PICTURE) || + strcasecmp(StorageMedium,UPNP_STORAGE_MICRO_MV) || + strcasecmp(StorageMedium,UPNP_STORAGE_MINI_DV) || + strcasecmp(StorageMedium,UPNP_STORAGE_NETWORK) || + strcasecmp(StorageMedium,UPNP_STORAGE_SACD) || + strcasecmp(StorageMedium,UPNP_STORAGE_S_VHS) || + strcasecmp(StorageMedium,UPNP_STORAGE_UNKNOWN) || + strcasecmp(StorageMedium,UPNP_STORAGE_VHS) || + strcasecmp(StorageMedium,UPNP_STORAGE_VHSC) || + strcasecmp(StorageMedium,UPNP_STORAGE_VIDEO8) || + strcasecmp(StorageMedium,UPNP_STORAGE_VIDEO_CD) || + strcasecmp(StorageMedium,UPNP_STORAGE_W_VHS) + ){ + ERROR("Invalid storage type: %s", StorageMedium); + return -1; + } + else { + this->mStorageMedium = StorageMedium; + } + return 0; +} + +/**********************************************\ +* * +* Mediator factory * +* * +\**********************************************/ cUPnPObjectFactory* cUPnPObjectFactory::mInstance = NULL; @@ -1704,4 +1818,94 @@ int cUPnPVideoBroadcastMediator::databaseToObject(cUPnPClassObject* Object, cUPn } } return 0; +} + +/**********************************************\ +* * +* Movie item mediator * +* * +\**********************************************/ + +cUPnPMovieMediator::cUPnPMovieMediator(cMediaDatabase* MediaDatabase) : + cUPnPVideoItemMediator(MediaDatabase){} + +cUPnPClassMovie* cUPnPMovieMediator::createObject(const char* Title, bool Restricted){ + MESSAGE("Creating movie '%s'",Title); + cUPnPClassMovie* Object = new cUPnPClassMovie; + if(this->initializeObject(Object, UPNP_CLASS_MOVIE, Title, Restricted)) return NULL; + return Object; +} + +cUPnPClassMovie* cUPnPMovieMediator::getObject(cUPnPObjectID ID){ + MESSAGE("Getting movie with ID '%s'",*ID); + cUPnPClassMovie* Object = new cUPnPClassMovie; + if(this->databaseToObject(Object, ID)) return NULL; + return Object; +} + +int cUPnPMovieMediator::objectToDatabase(cUPnPClassObject* Object){ + if(cUPnPVideoItemMediator::objectToDatabase(Object)) return -1; + cUPnPClassMovie* Movie = (cUPnPClassMovie*)Object; + cString Format = "INSERT OR REPLACE INTO %s (%s) VALUES (%s);"; + cString Statement=NULL, Columns=NULL, Values=NULL; + char *Value=NULL; + cString Properties[] = { + SQLITE_COL_OBJECTID, + SQLITE_COL_DVDREGIONCODE, + SQLITE_COL_STORAGEMEDIUM, + NULL + }; + for(cString* Property = Properties; *(*Property); Property++){ + Columns = cString::sprintf("%s%s%s", *Columns?*Columns:"", *Columns?",":"", *(*Property)); + if(!Movie->getProperty(*Property, &Value)){ + ERROR("No such property '%s' in object with ID '%s'",*(*Property),* Movie->getID()); + return -1; + } + char *escapedValue; + escapeSQLite(Value, &escapedValue); + Values = cString::sprintf("%s%s'%s'", *Values?*Values:"", *Values?",":"", escapedValue?escapedValue:"NULL"); + + } + Statement = cString::sprintf(Format, SQLITE_TABLE_MOVIES, *Columns, *Values); + if(this->mDatabase->execStatement(Statement)){ + ERROR("Error while executing statement"); + return -1; + } + return 0; +} + +int cUPnPMovieMediator::databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID){ + if(cUPnPVideoItemMediator::databaseToObject(Object,ID)){ + ERROR("Error while loading object"); + return -1; + } + cUPnPClassMovie* Movie = (cUPnPClassMovie*)Object; + cString Format = "SELECT * FROM %s WHERE %s=%s"; + cString Statement = NULL, Column = NULL, Value = NULL; + cRows* Rows; cRow* Row; + Statement = cString::sprintf(Format, SQLITE_TABLE_MOVIES, SQLITE_COL_OBJECTID, *ID); + if(this->mDatabase->execStatement(Statement)){ + ERROR("Error while executing statement"); + return -1; + } + Rows = this->mDatabase->getResultRows(); + if(!Rows->fetchRow(&Row)){ + MESSAGE("No item properties found"); + return 0; + } + while(Row->fetchColumn(&Column, &Value)){ + if(!strcasecmp(Column, SQLITE_COL_DVDREGIONCODE)){ + if(Movie->setDVDRegionCode(atoi(Value))){ + ERROR("Error while setting icon"); + return -1; + } + } + else if(!strcasecmp(Column, SQLITE_COL_STORAGEMEDIUM)){ + if(Movie->setStorageMedium(Value)){ + ERROR("Error while setting region"); + return -1; + } + } + } + return 0; }
\ No newline at end of file diff --git a/database/object.h b/database/object.h index 9da62db..a38098d 100644 --- a/database/object.h +++ b/database/object.h @@ -51,6 +51,7 @@ struct cClass { class cUPnPResource : public cListObject { friend class cUPnPResourceMediator; friend class cUPnPResources; + friend class cAudioVideoDetector; private: unsigned int mResourceID; cUPnPObjectID mObjectID; @@ -405,6 +406,17 @@ public: virtual cUPnPClassVideoBroadcast* getObject(cUPnPObjectID ID); }; +class cUPnPMovieMediator : public cUPnPVideoItemMediator { +protected: + virtual int objectToDatabase(cUPnPClassObject* Object); + virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); +public: + cUPnPMovieMediator(cMediaDatabase* MediaDatabase); + virtual ~cUPnPMovieMediator(){}; + virtual cUPnPClassMovie* createObject(const char* Title, bool Restricted); + virtual cUPnPClassMovie* getObject(cUPnPObjectID ID); +}; + class cUPnPContainerMediator : public cUPnPObjectMediator { protected: virtual int objectToDatabase(cUPnPClassObject* Object); diff --git a/database/resources.cpp b/database/resources.cpp index df2b354..bc4c185 100644 --- a/database/resources.cpp +++ b/database/resources.cpp @@ -10,6 +10,7 @@ #include "../upnpcomponents/dlna.h" #include <vdr/tools.h> #include "resources.h" +#include "../misc/avdetector.h" cUPnPResources* cUPnPResources::mInstance = NULL; @@ -94,6 +95,31 @@ cUPnPResource* cUPnPResources::getResource(unsigned int ResourceID){ } } +int cUPnPResources::createFromRecording(cUPnPClassVideoItem* Object, cRecording* Recording){ + cString VideoFile = cString::sprintf(VDR_RECORDFILE_PATTERN_TS, Recording->FileName(), 1); + + cAudioVideoDetector* Detector = new cAudioVideoDetector(); + + cString ContentType = "video/mpeg"; + cString ProtocolInfo = "http-get:*:video/mpeg:*"; + + cUPnPResource* Resource = this->mMediator->newResource(Object, UPNP_RESOURCE_RECORDING, Recording->FileName(), ContentType, ProtocolInfo); + + if(Detector->detectVideoProperties(Resource, VideoFile)){ + ERROR("Error while detecting video properties"); + return -1; + } + + delete Detector; + MESSAGE("To be done"); + return -1; +} + +int cUPnPResources::createFromFile(cUPnPClassItem* , cString ){ + MESSAGE("To be done"); + return -1; +} + int cUPnPResources::createFromChannel(cUPnPClassVideoBroadcast* Object, cChannel* Channel){ if(!Object || !Channel){ ERROR("Invalid input arguments"); |